on 12-02-2010 9:36 AM
How can I call word macro with parameters?
I have ms word document with macro, for example:
Sub Makro1(ByVal bookmark As String, ByVal text As String)
'
' Makro1 Makro
'
Selection.GoTo What:=wdGoToBookmark, Name:=bookmark
Selection.TypeText text:=text
ActiveDocument.Bookmarks(bookmark).Delete
.
.
.
End Sub
I try call this macro from webdynpro:
TRY.
CALL METHOD
wd_this->document->IF_IOS_APPLICATIONPROPERTIES~RUNMACRO
EXPORTING
NAME = 'Makro1("z1","test")'
ERRORINFORMATION = co_error_getcontent_stru
IMPORTING
RESULT =
.
CATCH CX_IOS_APPLICATIONPROPERTIES .
CATCH CX_IOS_COMMUNICATIONWRAPPER .
CATCH CX_IOS_ENVIRONMENT .
ENDTRY.
This macro cannot call. )
Calling a macro without parameters is ok.
Sub Makro2()
Call Makro1("z1", "test")
End Sub
CALL METHOD
wd_this->document->IF_IOS_APPLICATIONPROPERTIES~RUNMACRO
EXPORTING
NAME = 'Makro2'
ERRORINFORMATION = co_error_getcontent_stru
IMPORTING
RESULT =
Greats Radek
Hi Radek, sorry for reopening an old post, but have you found any documentation regarding the macro name parameter? It looks it accepts some sort of special figures:
e.g. '.macroname" looks for the macro in user's default template location.
Is there anything the DocumentName attribute of the office control does with this parameter?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi Jozef, I not found any documentation. I solved this problem by using format DOCX. DOCX is XML format. http://msdn.microsoft.com/en-us/library/documentformat.openxml.wordprocessing(v=office.14).aspx
Thanks for reply. We are using .DOTX (in fact it does not matter if .docx or .dotx is used). But we could not manage how to create the document, show it to the user, enable him to make changes etc.
Our scenario is pretty complicated, as we need to fill many parts of it dynamically (tables, formatting, CR_LF's, line-feeds, tabulators...).
Once you did find a way, what exactly did you do? Did you find a simple way to fill .docx?
Our scenario is:
1. Read template from BDS. In template .docx are empty bookmarks.
2. Fill bookmarks with data, all in xml. We can fill text, font, color, formating, tabs, line-feeds, word tables, etc. All is in abap, xml.
3. Filled docx display in abap webdynpro with officecontrol. User can edit this document.
4. Get the edited document from officecontrol after click at Save in our WD application.
5. Check if some bookmarks have not changed values. If all is ok, store edited document in CRM.
Thank you very much for the explanation. But I need to ask you how do you parse and edit .docx as a plain xml file in ABAP?
An .docx is a zipped file consisting of many xml files. So to be able to do what you wrote, you will first need to:
1. download the file from some location (I believe it does not matter whether the file is in the MIME repository = my case, in BDS = your case, some content server, stored using GOS or whatever). You always will get the binary. Correct?
2. unzip the file (which you only can do using a third-party tool, installed on the server, or is there another way?). By unzipping, you will get a couple of files, that you need to store somewhere (the application server or whatever). Correct?
3. then you have got some files, which you can parse and look for the bookmarks, fill your text, be it whatever needed. I'm not very at-home about the whole structure of the xml-s belonging to .docx, but probably you can use a bookmark to fill "real data" that will be shown.
4. store all the files back to a place, where you are able to call another system-command to zip the files to the .docx file type. Correct?
5. upload where needed (once you again can have the binary, it should be possible to store it anywhere).
So please, is this your approach? Or did you find a simplier way of doing this? Unfortunately, I'm on a ECC 6.0 with not the most actual support packs without the possibility to do anything about it .
1. Yes. Download from some location as binary file.
2. Unzip by class CL_ABAP_ZIP. For filling bookmarks i need file 'word/document.xml'.
CL_ABAP_ZIP->GET
Unzipped files are only in memory.
3. For parsing and filling bookmarks i use classes and interfaces cl_ixml, if_ixml*
* create a DOM from the xstring
lr_ixml = cl_ixml=>create( ).
lr_stream_factory = lr_ixml->create_stream_factory( ).
lr_istream = lr_stream_factory->create_istream_xstring( iv_docx ).
lr_document = lr_ixml->create_document( ).
gr_document = lr_document.
lr_parser = lr_ixml->create_parser( document = lr_document
istream = lr_istream
stream_factory = lr_stream_factory ).
CALL METHOD LR_PARSER->ADD_PRESERVE_SPACE_ELEMENT
RECEIVING
RVAL = lv_rval.
IF lv_rval <> abap_true.
* Err in parser XML
ENDIF.
CALL METHOD LR_PARSER->SET_XML_SPACE_AWARE.
IF lv_rval <> abap_true.
* Err in parser XML
ENDIF.
* Finding and filling bookmarks
lr_root = gr_document->get_root_element( ).
* All elements "w:bookmarkStart"
lr_elements = LR_ROOT->GET_ELEMENTS_BY_TAG_NAME(
* DEPTH = 0
NAME = 'bookmarkStart'
NAMESPACE = 'w'
).
lr_itr_bookmarkStart = lr_elements->create_iterator( ).
DO.
lr_node = lr_itr_bookmarkStart->get_next( ).
IF lr_node IS INITIAL. EXIT. ENDIF.
lr_attributes = lr_node->get_attributes( ).
* Read attribute "w:name" of element "w:bookmarkStart"
lr_attribute = lr_attributes->get_named_item(
NAME = 'name'
NAMESPACE = 'w'
).
lv_name = lr_attribute->get_value( ).
if iv_name <> lv_name. continue. endif.
* Element "w:fldSimple" was found, iv_name = Name of bookmark to fill
lv_bookmark_found = abap_true.
lr_node_bookmarkStart = lr_node.
* Read attribute "w:id" of element "w:bookmarkStart"
lr_attribute = lr_attributes->get_named_item(
NAME = 'id'
NAMESPACE = 'w'
).
lv_id_start = lr_attribute->get_value( ).
clear lv_id_end.
* .... work with parser
* find element w:bookmarkEnd for relevant w:bookmarkStart, bookmarkEnd with the same id as bookmarkStart
lr_node_next = lr_node->get_next( ).
do.
IF lr_node_next IS INITIAL. EXIT. ENDIF.
lr_node = lr_node_next.
lv_name = lr_node->get_name( ).
if lv_name = 'bookmarkEnd'.
lr_attributes = lr_node->get_attributes( ).
* Read attribute "w:id" of element "w:bookmarkEnd"
lr_attribute = lr_attributes->get_named_item(
NAME = 'id'
NAMESPACE = 'w'
).
lv_id_end = lr_attribute->get_value( ).
endif.
if lv_id_start = lv_id_end.
lr_node_parent = lr_node->get_parent( ).
lr_node_bookmarkEnd = lr_node.
er_node_bookmarkEnd = lr_node.
exit.
else.
lr_node_next = lr_node->get_next( ).
* remove elements between bookmarkStart and bookmarkEnd
lr_node->remove_node( ).
endif.
enddo.
* insert new elements between boomarkStart and bookmarkEnd
CALL METHOD me->XML_RUN_TEXT_ADD
EXPORTING
IR_PARENT = lr_node_parent
IR_REF = lr_node_bookmarkEnd
IV_VALUE = iv_value
IMPORTING
EV_OK = lv_bookmark_ok.
EXIT.
ENDDO.
For example, XML with bookmark:
<w:bookmarkStart w:id="0" w:name="testing123"/>
<w:r>
<w:t>This is sentence two.</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t xml:space="preserve">This </w:t>
</w:r>
<w:bookmarkEnd w:id="0"/>
4. replace file 'word/document.xml' in zip (.docx) with class CL_ABAP_ZIP.
CL_ABAP_ZIP->DELETE
CL_ABAP_ZIP->ADD
5. You can store result where you need.
6. You can use for editing by users classic dynpro with container with word.
Work with parser is simply. Its repeating use of few methods of interfaces if_ixml* (if_ixml_node, if_ixml_element, if_ixml_node_list, IF_IXML_NODE_COLLECTION, if_ixml_node_iterator, IF_IXML_NAMED_NODE_MAP, IF_IXML_ATTRIBUTE). Structure of docx xml you can find at MSDN or you cat create word document, save it, rename .docx->.zip, open file word/document.xml in internet explorer.
Example of creating xml element with attributes:
* FONT=val
* create child "w:rFonts"
lr_element = gr_document->create_element(
name = 'rFonts'
namespace = 'w' ).
lr_child_prop ?= lr_element.
lr_attribute = gr_document->create_attribute(
name = 'ascii'
namespace = 'w' ).
lr_prop_attrib ?= lr_attribute.
lv_rc = lr_prop_attrib->SET_VALUE( value = 'Arial' ).
lr_attributes = lr_child_prop->get_attributes( ).
lv_rc = LR_ATTRIBUTES->SET_NAMED_ITEM( node = lr_prop_attrib ).
lr_attribute = gr_document->create_attribute(
name = 'hAnsi'
namespace = 'w' ).
lr_prop_attrib ?= lr_attribute.
lv_rc = lr_prop_attrib->SET_VALUE( value = 'Arial' ).
lv_rc = LR_ATTRIBUTES->SET_NAMED_ITEM( node = lr_prop_attrib ).
lr_attribute = gr_document->create_attribute(
name = 'cs'
namespace = 'w' ).
lr_prop_attrib ?= lr_attribute.
lv_rc = lr_prop_attrib->SET_VALUE( value = 'Arial' ).
lv_rc = LR_ATTRIBUTES->SET_NAMED_ITEM( node = lr_prop_attrib ).
lv_rc = lr_child_Pr->append_child( lr_child_prop ).
XML:
* Text properties:
* <w:r>
* <w:rPr>
* <w:rFonts w:ascii="Arial" w:hAnsi="Arial" w:cs="Arial" />
* <w:sz w:val="44" />
* <w:szCs w:val="44" />
* <w:b />
* <w:imprint />
* <w:lang w:val="en-ca" />
* </w:rPr>
* </w:r>
If You don't set text properties in bookmark, word use text properties from parent paragraph. In most cases is sufficient set text "value" in bookmark.
You are right the whole parsing part should be easy. But in the process, where user should be able to change the document content and you want to parse the text, this is not that easy at all. Bookmars are maybe suitable a little bit as a replacement of real merge-fields. But only one-way there, not the other way out.
User | Count |
---|---|
91 | |
10 | |
10 | |
9 | |
9 | |
7 | |
6 | |
5 | |
5 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.