Here is an example of creating word documents from templates stored in web repository (SMW0) using wordprocessingml.
A very simple form can be done in around an hour of time.
data: LO_FORM type ref to Z_MWL_FORM.
data: L_TEMPLATE type STRING value 'block'.
data: L_INDEX type I value 1.
data: L_NUM type I.
create object LO_FORM
exporting
I_TEMPLATE = 'Z_TEST'.
LO_FORM->REPLICATE(
I_TEMPLATE_ID = L_TEMPLATE
I_COPY_NUM = 2
).
LO_FORM->PREP_SEQ_ACCESS( ).
if LO_FORM->FIND_VARIABLE( 'name' ) eq ABAP_TRUE.
LO_FORM->SET_VALUE( 'Zhambyl').
endif.
if LO_FORM->FIND_VARIABLE( 'age' ) eq ABAP_TRUE.
LO_FORM->SET_VALUE( '25' ).
endif.
if LO_FORM->FIND_VARIABLE( 'gender' ) eq ABAP_TRUE.
LO_FORM->SET_VALUE( 'male' ).
endif.
do 2 times.
if LO_FORM->FIND_BLOCK( L_INDEX ) eq ABAP_TRUE.
if LO_FORM->FIND_VARIABLE( 'var1' ) eq ABAP_TRUE.
LO_FORM->SET_VALUE( '1' ).
endif.
if LO_FORM->FIND_VARIABLE( 'var2' ) eq ABAP_TRUE.
LO_FORM->SET_VALUE( '2' ).
endif.
if LO_FORM->FIND_VARIABLE( 'var3' ) eq ABAP_TRUE.
LO_FORM->SET_VALUE( '3' ).
endif.
endif.
add 1 to L_INDEX.
enddo.
LO_FORM->FINISH_SEQ_ACCESS( ).
LO_FORM->CLEAN( ).
LO_FORM->DISPLAY( ).
class Z_MWL_FILE definition
public
create public .
public section.
data EXTENSION type STRING .
data TEMPDIR type STRING .
data BSTRING type XSTRING.
methods: DOWNLOAD " download file from web repository
importing
VALUE(I_TEMPLATE) type STRING
returning
VALUE(R_SUBRC) like SY-SUBRC.
methods GET_BSTRING " returns xstring representation of file
returning
VALUE(R_STRING) type XSTRING.
methods GET_TEMP_DIR " chose file storage location
returning
VALUE(R_PATH) type string.
methods SAVE_ON_FRONTEND " upload file to client
importing
VALUE(I_STRING) type XSTRING
returning
VALUE(R_SUBRC) like SY-SUBRC.
protected section.
private section.
ENDCLASS.
CLASS Z_MWL_FILE IMPLEMENTATION.
method DOWNLOAD.
data: LS_KEY type WWWDATATAB.
data: LS_MIME type W3MIME.
data: LT_MIME type standard table of W3MIME.
field-symbols <LFS_DATA> type ANY.
LS_KEY-RELID = 'MI'.
LS_KEY-OBJID = I_TEMPLATE.
call function 'WWWDATA_IMPORT'
exporting
KEY = LS_KEY
tables
MIME = LT_MIME
exceptions
WRONG_OBJECT_TYPE = 1
IMPORT_ERROR = 2
others = 3.
if SY-SUBRC eq 0.
loop at LT_MIME into LS_MIME.
assign LS_MIME to <LFS_DATA> casting type ('X').
if <LFS_DATA> is assigned.
concatenate BSTRING <LFS_DATA> into BSTRING in byte mode.
unassign <LFS_DATA>.
endif.
endloop.
else.
R_SUBRC = SY-SUBRC.
endif.
endmethod. "DOWNLOAD
method GET_BSTRING.
R_STRING = BSTRING.
endmethod. "GET_BSTRING
method GET_TEMP_DIR.
data: L_WTITLE type STRING.
data: L_NAME type STRING.
data: L_FPATH type STRING.
L_WTITLE = 'CHOSE FILE STORAGE LOCATION'.
CL_GUI_FRONTEND_SERVICES=>FILE_SAVE_DIALOG(
exporting
WINDOW_TITLE = L_WTITLE
DEFAULT_EXTENSION = 'docx'
FILE_FILTER = 'docx'
changing
FILENAME = L_NAME
PATH = TEMPDIR
FULLPATH = L_FPATH ).
CL_GUI_CFW=>FLUSH( ).
R_PATH = L_FPATH.
endmethod. "GET_TEMP_DIR
method SAVE_ON_FRONTEND.
data: LV_FILE_TAB type standard table of SOLISTI1,
LV_BYTECOUNT type I.
data: L_FPATH type STRING.
call function 'SCMS_XSTRING_TO_BINARY'
exporting
BUFFER = I_STRING
importing
OUTPUT_LENGTH = LV_BYTECOUNT
tables
BINARY_TAB = LV_FILE_TAB.
"Save the file
L_FPATH = GET_TEMP_DIR( ).
if L_FPATH is not initial.
CL_GUI_FRONTEND_SERVICES=>GUI_DOWNLOAD(
exporting
BIN_FILESIZE = LV_BYTECOUNT
FILENAME = L_FPATH
FILETYPE = 'BIN'
changing
DATA_TAB = LV_FILE_TAB
).
if SY-SUBRC ne 0.
R_SUBRC = SY-SUBRC.
endif.
else.
R_SUBRC = 2.
endif.
endmethod. "SAVE_ON_FRONTEND
ENDCLASS.
This class relies on classes found in packages: S_OOXML_CORE, SXML and XSLT transformations.
class Z_MWL_FORM definition
public
create public .
public section.
data: MAIN_PART type XSTRING .
data: DOCUMENT type XSTRING .
data: INTRM_PART type XSTRING .
data: FINAL_DOC type XSTRING.
methods CONSTRUCTOR importing I_TEMPLATE type STRING. " Finds the main part of word document from zip pakcage container and
" stores it. I_TEMPLATE is the logical name of the file in smw0
methods DISPLAY. " This method packages updated main part and uploads it to front-end. Dont mind the name.
methods REPLICATE " Replicates marked block of text using transformations and substitues standard markups for custom ones
importing I_TEMPLATE_ID type STRING
I_COPY_NUM type I.
methods: FIND_VARIABLE " Finds tag named variable using sxml. I_var is a value for name attribute of this tag.
importing I_VAR type STRING
returning VALUE(RV_FOUND) type ABAP_BOOL.
methods: FIND_BLOCK importing I_BLOCK type I " Finds tag named block using sxml. I_block is a value for number attribute of this tag.
returning VALUE(RV_FOUND) type ABAP_BOOL. " Block contains several variables that can be copyed with different block numbers
methods: SET_VALUE importing I_VAL type STRING. " Replaces value of placeholder variable
methods: PREP_SEQ_ACCESS. " Converts xstring to Xml objects and prepares them for sequencial access
methods: FINISH_SEQ_ACCESS. " Converts from sXML back to xstring representation
methods CLEAN. " Clear's all the custom mark up from main part of word document
protected section.
data: O_FILE type ref to ZCL_ZK_MWL_FILE.
data: O_DOC type ref to CL_DOCX_DOCUMENT.
data: O_DOCUMENTPART type ref to CL_DOCX_MAINDOCUMENTPART.
data: O_SREADER type ref to IF_SXML_READER.
data: O_SWRITER type ref to IF_SXML_WRITER.
data: O_SNODE type ref to IF_SXML_NODE.
data: O_SVALUE_NODE type ref to IF_SXML_VALUE_NODE.
private section.
ENDCLASS.
CLASS Z_MWL_FORM IMPLEMENTATION.
method CLEAN.
if INTRM_PART is not initial.
call transformation Z_CLEAN
source xml INTRM_PART
result xml FINAL_DOC.
endif.
endmethod. "CLEAN
method CONSTRUCTOR.
create object O_FILE.
O_FILE->DOWNLOAD( I_TEMPLATE ).
DOCUMENT = O_FILE->GET_BSTRING( ).
try.
O_DOC = CL_DOCX_DOCUMENT=>LOAD_DOCUMENT( IV_DATA = DOCUMENT ).
* get the maindocument part
O_DOCUMENTPART = O_DOC->GET_MAINDOCUMENTPART( ).
MAIN_PART = O_DOCUMENTPART->GET_DATA( ).
catch CX_OPENXML_FORMAT.
catch CX_OPENXML_NOT_ALLOWED.
catch CX_OPENXML_NOT_FOUND.
catch CX_TRANSFORMATION_ERROR.
endtry.
endmethod. "constructor
method DISPLAY.
if FINAL_DOC is not initial.
O_DOCUMENTPART->FEED_DATA( FINAL_DOC ).
elseif MAIN_PART is not initial.
O_DOCUMENTPART->FEED_DATA( MAIN_PART ).
endif.
FINAL_DOC = O_DOC->GET_PACKAGE_DATA( ).
if O_FILE->SAVE_ON_FRONTEND( FINAL_DOC ) ne 0.
message 'Выгрузка отменена' type 'S'.
endif.
endmethod. "Display
method FIND_BLOCK.
data: LX_ROOT type ref to CX_SXML_ERROR.
data: LO_OPELEM type ref to IF_SXML_OPEN_ELEMENT.
data: L_AT_VAL type ref to IF_SXML_VALUE.
data: L_VAL type STRING.
if O_SREADER is bound and O_SWRITER is bound.
while RV_FOUND ne ABAP_TRUE.
try.
O_SNODE = O_SREADER->READ_NEXT_NODE( ).
if O_SNODE is initial.
exit.
endif.
if O_SNODE->TYPE eq IF_SXML_NODE=>CO_NT_ELEMENT_OPEN.
LO_OPELEM ?= O_SNODE.
if LO_OPELEM->IF_SXML_NAMED~QNAME-NAME eq 'block'.
L_AT_VAL = LO_OPELEM->GET_ATTRIBUTE_VALUE( 'num' ).
L_VAL = L_AT_VAL->GET_VALUE( ).
if L_VAL eq I_BLOCK.
RV_FOUND = ABAP_TRUE.
endif.
endif.
endif.
O_SWRITER->WRITE_NODE( O_SNODE ).
catch CX_SXML_ERROR into LX_ROOT.
exit.
endtry.
endwhile.
endif.
endmethod. "FIND_BLOCK
method FIND_VARIABLE.
data: LX_ROOT type ref to CX_SXML_ERROR.
data: LO_OPELEM type ref to IF_SXML_OPEN_ELEMENT.
data: L_AT_VAL type ref to IF_SXML_VALUE.
data: L_VAL type STRING.
if O_SREADER is bound and O_SWRITER is bound.
while RV_FOUND ne ABAP_TRUE.
try.
O_SNODE = O_SREADER->READ_NEXT_NODE( ).
if O_SNODE is initial.
exit.
endif.
if O_SNODE->TYPE eq IF_SXML_NODE=>CO_NT_ELEMENT_OPEN.
LO_OPELEM ?= O_SNODE.
if LO_OPELEM->IF_SXML_NAMED~QNAME-NAME eq 'variable'.
L_AT_VAL = LO_OPELEM->GET_ATTRIBUTE_VALUE( 'mark' ).
L_VAL = L_AT_VAL->GET_VALUE( ).
if L_VAL eq I_VAR.
RV_FOUND = ABAP_TRUE.
endif.
endif.
endif.
O_SWRITER->WRITE_NODE( O_SNODE ).
catch CX_SXML_ERROR into LX_ROOT.
exit.
endtry.
endwhile.
clear RV_FOUND.
while RV_FOUND ne ABAP_TRUE.
try.
O_SNODE = O_SREADER->READ_NEXT_NODE( ).
if O_SNODE is initial.
exit.
endif.
if O_SNODE->TYPE eq IF_SXML_NODE=>CO_NT_ELEMENT_OPEN.
LO_OPELEM ?= O_SNODE.
if LO_OPELEM->IF_SXML_NAMED~QNAME-NAME eq 't'.
RV_FOUND = ABAP_TRUE.
endif.
endif.
O_SWRITER->WRITE_NODE( O_SNODE ).
catch CX_SXML_ERROR into LX_ROOT.
exit.
endtry.
endwhile.
clear RV_FOUND.
while RV_FOUND ne ABAP_TRUE.
try.
O_SNODE = O_SREADER->READ_NEXT_NODE( ).
if O_SNODE is initial.
exit.
endif.
if O_SNODE->TYPE eq IF_SXML_NODE=>CO_NT_VALUE.
O_SVALUE_NODE ?= O_SNODE.
RV_FOUND = ABAP_TRUE.
exit.
endif.
O_SWRITER->WRITE_NODE( O_SNODE ).
catch CX_SXML_ERROR into LX_ROOT.
exit.
endtry.
endwhile.
endif.
endmethod. "FIND_VARIABLE
method FINISH_SEQ_ACCESS.
data: LX_ROOT type ref to CX_SXML_ERROR.
data: LO_WRITER type ref to CL_SXML_STRING_WRITER.
if O_SREADER is not initial and O_SWRITER is bound.
do.
try.
O_SNODE = O_SREADER->READ_NEXT_NODE( ).
if O_SNODE is initial.
exit.
endif.
O_SWRITER->WRITE_NODE( O_SNODE ).
catch CX_SXML_ERROR into LX_ROOT.
exit.
endtry.
enddo.
try.
LO_WRITER ?= O_SWRITER.
INTRM_PART = LO_WRITER->GET_OUTPUT( ).
catch CX_SXML_ERROR into LX_ROOT.
exit.
endtry.
endif.
endmethod. "FINISH_SEQ_ACCESS
method PREP_SEQ_ACCESS.
if INTRM_PART is not initial.
O_SREADER ?= CL_SXML_STRING_READER=>CREATE( INTRM_PART ).
O_SWRITER ?= CL_SXML_STRING_WRITER=>CREATE( ).
endif.
endmethod. "prep_seq_access
method REPLICATE.
if INTRM_PART is initial.
call transformation Z_REPLICATE
source xml MAIN_PART
result xml INTRM_PART
parameters TEMPLATE_ID = I_TEMPLATE_ID
COPY_NUM = I_COPY_NUM.
else.
call transformation Z_REPLICATE
source xml INTRM_PART
result xml INTRM_PART
parameters TEMPLATE_ID = I_TEMPLATE_ID
COPY_NUM = I_COPY_NUM.
endif.
endmethod. "replicate
method SET_VALUE.
data: LX_ROOT type ref to CX_SXML_ERROR.
data: L_XSTRING type XSTRING.
* L_XSTRING = CL_ABAP_CODEPAGE=>CONVERT_TO( I_VAL ).
if O_SVALUE_NODE is bound and O_SWRITER is bound.
try.
O_SVALUE_NODE->IF_SXML_VALUE~SET_VALUE( I_VAL ).
O_SWRITER->WRITE_NODE( O_SNODE ).
catch CX_SXML_ERROR into LX_ROOT.
exit.
endtry.
endif.
endmethod. "set_value
ENDCLASS.
<xsl:transformxmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:sap="http://www.sap.com/sapxsl"xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" version="1.0">
<xsl:output encoding="UTF-8" indent="yes" method="xml" omit-xml-declaration="no" standalone="yes"/>
<xsl:param name="TEMPLATE_ID"/>
<xsl:param name="COPY_NUM" sap:type="number"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="w:sdt">
<xsl:choose>
<xsl:when test="descendant::w:tag[@w:val=$TEMPLATE_ID]">
<xsl:call-template name="multiply">
<xsl:with-param name="maxCount" select="$COPY_NUM"/>
<xsl:with-param name="nodeToCopy" select="."/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:element name="variable">
<xsl:attribute name="mark">
<xsl:value-of select="descendant::w:tag/@w:val"/>
</xsl:attribute>
<xsl:apply-templates select="w:sdtContent/node()|@*" mode="variable"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="multiply">
<xsl:param name="maxCount"/>
<xsl:param name="i" select="1"/>
<xsl:param name="nodeToCopy"/>
<xsl:choose>
<xsl:when test="$i <= $maxCount">
<xsl:element name="block">
<xsl:attribute name="num">
<xsl:value-of select="$i"/>
</xsl:attribute>
<!-- <xsl:copy-of select="$nodeToCopy/w:sdtContent/node()|@*"/>-->
<xsl:apply-templates select="$nodeToCopy/w:sdtContent/node()|@*"/>
</xsl:element>
<xsl:call-template name="multiply">
<xsl:with-param name="maxCount" select="$maxCount"/>
<xsl:with-param name="nodeToCopy" select="$nodeToCopy"/>
<xsl:with-param name="i" select="$i+1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<xsl:template match="node()|@*" mode="variable">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="variable"/>
</xsl:copy>
</xsl:template>
<xsl:template match="w:sdtContent/w:r[1]" mode="variable">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="variable"/>
</xsl:copy>
</xsl:template>
<xsl:template match="w:sdtContent/w:r[position() != 1]" mode="variable">
</xsl:template>
</xsl:transform>
<xsl:transformxmlns:xsl="http://www.w3.org/1999/XSL/Transform"xmlns:sap="http://www.sap.com/sapxsl"xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" version="1.0">
<xsl:output encoding="UTF-8" indent="yes" method="xml" omit-xml-declaration="no" standalone="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="variable">
<xsl:apply-templates select="node()|@*"/>
</xsl:template>
<xsl:template match="block">
<xsl:apply-templates select="node()|@*"/>
</xsl:template>
</xsl:transform>
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
4 | |
3 | |
2 | |
2 | |
2 | |
1 | |
1 | |
1 | |
1 |