Одина из самых популярных разработок ZWWW не может(по крайней мере те версии, которые я видел) формировать документы при фоновой работе приложения. Второй недостаток это скорость обработки. Эти проблемы можно решить используя ABAP2XLSX или XLSX Workbench, но порой их может не быть на проекте. В таком случае для формирования документа EXCEL можно воспользоваться трансформациями.
- Создадим документ EXCEL с необходимым форматированием
2. Сохраним его как таблицу xml 2003.
Если открыть документ в текстовом редакторе можно увидеть его структуру(Полный код XML далее)
Тег <DocumentProperties> содержит свойства документа. Информация об авторе и времени создания, в общем случае нам это не интересно. Но, возможно, вам потребуется вывести туда, например, создателя документа.
Тег <Styles> содержит набор стилей для всего документа. Если нам необходимо доработать существующий документ. Мы можем в другом документе создать страницу с необходимыми стилями. Типа такой:
Сохранить ее как XML и скопировать нужный стиль в существующий докyмент. Только надо смотреть, чтобы коды отличались. Объединение ячеек просто стилем делать нельзя. Надо немного изменять в части со структурой документа.
Далее идут блоки листа, содержащие в себе структуру. Можно создавать новые листы, менять свойства ячеек, добавлять информацию.
Эта информация пригодится, например, если вы будете форматировать готовую трансформацию. Т.к. в дальнейшем документ будет приведен в не перевариваемый для EXCEL вид. И Редактирование будет именно в структуре XML, а не визуальное. Вообще, подобный способ мне нравится меньше, чем формирование через ABAP2XLSX, где можно сохранить шаблон в нормальном для редактирования виде.
3. Создадим тип данных для передачи в трансформацию. Входных параметров может быть много, но мне удобнее подавать все в одной структуре.
4. Теперь перейдем в транзакцию STRANS и создадим простую трансформацию
Если зайти в трансформацию, то увидим следующий код:
Для того, чтобы работать с объектами словаря, надо прописать в тег transformation следующий атрибут:
Между тегами <tt:template> -вставляем весь ранее сохраненный xml документ.
Далее надо добавить данные из внутренней структуры в документ
Прописываем входные параметры: <tt:root name="MAINDATA" type="ddic:ZZZ_S_TEST_XLS"/>. В нашем случае это одна структура с вложенными таблицами
1 2 3 4 |
<?sap.transform simple?> <tt:transform xmlns:tt="http://www.sap.com/transformation-templates" xmlns:ddic="http://www.sap.com/abapxml/types/dictionary" xmlns:def="http://www.sap.com/abapxml/types/defined"> <tt:root name="MAINDATA" type="ddic:ZZZ_S_TEST_XLS"/> <tt:template> |
Теперь мы можем обращаться к этой структуре в теле трансформации.
Для вставки единичного значения используем тег <tt:value
1 2 3 4 5 6 7 8 9 10 |
<Data ss:Type="String" > <tt:value ref=".MAINDATA.SHOP"/> </Data> </Cell> </Row> <Row ss:AutoFitHeight="0"> <Cell ss:StyleID="s113"> <Data ss:Type="String">Наименование</Data> </Cell> <Cell ss:StyleID="s113"> <Data ss:Type="String">Цена</Data> </Cell> |
Для вставки табличного значения необходимо использовать <tt:loop
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<Row ss:AutoFitHeight="0"> <Cell ss:StyleID="s113"> <Data ss:Type="String">Наименование</Data> </Cell> <Cell ss:StyleID="s113"> <Data ss:Type="String">Цена</Data> </Cell> <Cell ss:StyleID="s113"> <Data ss:Type="String">Количество</Data> </Cell> </Row> <tt:loop ref=".MAINDATA.PRICELIST" name="TABLE"> <Row ss:AutoFitHeight="0"> <Cell ss:StyleID="s113"> <Data ss:Type="String"> <tt:value ref="$TABLE.NAME"/> </Data> </Cell> <Cell ss:StyleID="s113"> <Data ss:Type="String"> <tt:value ref="$TABLE.PRICE"/> </Data> </Cell> <Cell ss:StyleID="s113"> <Data ss:Type="String"> <tt:value ref="$TABLE.COL"/> </Data> </Cell> </Row> </tt:loop> <Row ss:AutoFitHeight="0"> <Cell ss:StyleID="s114"> <Data ss:Type="String">Менеджер:</Data> </Cell> <Cell ss:Index="3" ss:StyleID="s116"> <Data ss:Type="String" tt:value-ref="MAINDATA.MANAGER"> </Data> </Cell> |
Если наша трансформация предполагает добавление строк, необходимо удалить это свойство листа. Или менять его самостоятельно
Если в получившемся документе будет ошибка, увидим такое окошко при открытии
Можно посмотреть более подробную информацию об ошибке по ссылке
Линий тег, который фиксирует строку, и при добавлении строк выше получается коллизия. Удалим его
В результате получаем такой XML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
<?sap.transform simple?> <tt:transform xmlns:tt="http://www.sap.com/transformation-templates" xmlns:ddic="http://www.sap.com/abapxml/types/dictionary" xmlns:def="http://www.sap.com/abapxml/types/defined"> <tt:root name="MAINDATA" type="ddic:ZZZ_S_TEST_XLS"/> <tt:template> <?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html= "http://www.w3.org/TR/REC-html40"> <DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"> <Author>Pashigorev A.</Author> <LastAuthor>Пашигорев Александр Юрьевич</LastAuthor> <Created>2021-03-04T13:13:54Z</Created> <LastSaved>2021-03-05T09:52:44Z</LastSaved> <Company>Home</Company> <Version>16.00</Version> </DocumentProperties> <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"> <AllowPNG/> </OfficeDocumentSettings> <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"> <WindowHeight>12285</WindowHeight> <WindowWidth>28800</WindowWidth> <WindowTopX>0</WindowTopX> <WindowTopY>0</WindowTopY> <ProtectStructure>False</ProtectStructure> <ProtectWindows>True</ProtectWindows> </ExcelWorkbook> <Styles> <Style ss:ID="Default" ss:Name="Normal"> <Alignment ss:Vertical="Bottom"/> <Borders/> <Font ss:Color="#000000" ss:FontName="Times New Roman" ss:Size="12" x:CharSet="204" x:Family="Swiss"/> <Interior/> <NumberFormat/> <Protection/> </Style> <Style ss:ID="s112"> <Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/> <Borders> <Border ss:LineStyle="Continuous" ss:Position="Bottom" ss:Weight="1"/> <Border ss:LineStyle="Continuous" ss:Position="Left" ss:Weight="1"/> <Border ss:LineStyle="Continuous" ss:Position="Right" ss:Weight="1"/> <Border ss:LineStyle="Continuous" ss:Position="Top" ss:Weight="1"/> </Borders> <Interior ss:Color="#D6DCE4" ss:Pattern="Solid"/> </Style> <Style ss:ID="s113"> <Borders> <Border ss:LineStyle="Continuous" ss:Position="Bottom" ss:Weight="1"/> <Border ss:LineStyle="Continuous" ss:Position="Left" ss:Weight="1"/> <Border ss:LineStyle="Continuous" ss:Position="Right" ss:Weight="1"/> <Border ss:LineStyle="Continuous" ss:Position="Top" ss:Weight="1"/> </Borders> </Style> <Style ss:ID="s114"> <Font ss:Bold="1" ss:Color="#000000" ss:FontName="Times New Roman" ss:Size="12" x:CharSet="204" x:Family="Roman"/> </Style> <Style ss:ID="s116"> <Borders> <Border ss:LineStyle="Continuous" ss:Position="Bottom" ss:Weight="1"/> </Borders> </Style> </Styles> <Worksheet ss:Name="Лист1"> <Table ss:DefaultColumnWidth="54" ss:DefaultRowHeight="15.75" ss:ExpandedColumnCount="3" x:FullColumns="1" x:FullRows="1"> <Column ss:AutoFitWidth="0" ss:Width="85.5"/> <Column ss:AutoFitWidth="0" ss:Width="65.25"/> <Column ss:AutoFitWidth="0" ss:Width="63.75"/> <Row ss:AutoFitHeight="0"> <Cell ss:MergeAcross="2" ss:StyleID="s112"> <Data ss:Type="String" > <tt:value ref=".MAINDATA.SHOP"/> </Data> </Cell> </Row> <Row ss:AutoFitHeight="0"> <Cell ss:StyleID="s113"> <Data ss:Type="String">Наименование</Data> </Cell> <Cell ss:StyleID="s113"> <Data ss:Type="String">Цена</Data> </Cell> <Cell ss:StyleID="s113"> <Data ss:Type="String">Количество</Data> </Cell> </Row> <tt:loop ref=".MAINDATA.PRICELIST" name="TABLE"> <Row ss:AutoFitHeight="0"> <Cell ss:StyleID="s113"> <Data ss:Type="String"> <tt:value ref="$TABLE.NAME"/> </Data> </Cell> <Cell ss:StyleID="s113"> <Data ss:Type="String"> <tt:value ref="$TABLE.PRICE"/> </Data> </Cell> <Cell ss:StyleID="s113"> <Data ss:Type="String"> <tt:value ref="$TABLE.COL"/> </Data> </Cell> </Row> </tt:loop> <Row ss:AutoFitHeight="0"> <Cell ss:StyleID="s114"> <Data ss:Type="String">Менеджер:</Data> </Cell> <Cell ss:Index="3" ss:StyleID="s116"> <Data ss:Type="String" tt:value-ref="MAINDATA.MANAGER"> </Data> </Cell> </Row> </Table> <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"> <PageSetup> <Header x:Margin="0.3"/> <Footer x:Margin="0.3"/> <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/> </PageSetup> <Unsynced/> <Print> <ValidPrinterInfo/> <PaperSizeIndex>9</PaperSizeIndex> <HorizontalResolution>600</HorizontalResolution> <VerticalResolution>600</VerticalResolution> </Print> <Selected/> <Panes> <Pane> <Number>3</Number> <ActiveRow>30</ActiveRow> <ActiveCol>1</ActiveCol> </Pane> </Panes> <ProtectObjects>False</ProtectObjects> <ProtectScenarios>False</ProtectScenarios> </WorksheetOptions> </Worksheet> <Worksheet ss:Name="Лист2"> <Table ss:DefaultColumnWidth="54" ss:DefaultRowHeight="15.75" ss:ExpandedColumnCount="1" ss:ExpandedRowCount="1" x:FullColumns="1" x:FullRows="1"> <Row ss:AutoFitHeight="0"> <Cell> <Data ss:Type="String">Данные List 2</Data> </Cell> </Row> </Table> <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"> <PageSetup> <Header x:Margin="0.3"/> <Footer x:Margin="0.3"/> <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/> </PageSetup> <Unsynced/> <Panes> <Pane> <Number>3</Number> <ActiveRow>2</ActiveRow> </Pane> </Panes> <ProtectObjects>False</ProtectObjects> <ProtectScenarios>False</ProtectScenarios> </WorksheetOptions> </Worksheet> <Worksheet ss:Name="Лист3"> <Table ss:DefaultColumnWidth="54" ss:DefaultRowHeight="15.75" ss:ExpandedColumnCount="1" ss:ExpandedRowCount="1" x:FullColumns="1" x:FullRows="1"> <Row ss:AutoFitHeight="0"/> </Table> <WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"> <PageSetup> <Header x:Margin="0.3"/> <Footer x:Margin="0.3"/> <PageMargins x:Bottom="0.75" x:Left="0.7" x:Right="0.7" x:Top="0.75"/> </PageSetup> <Unsynced/> <ProtectObjects>False</ProtectObjects> <ProtectScenarios>False</ProtectScenarios> </WorksheetOptions> </Worksheet> </Workbook> </tt:template> </tt:transform> |
Код для запуска трансформации. Обратите внимание, что имя источника данных должно совпадать с тем, которое мы прописали для него в трансформации в теге root
1 |
START-OF-SELECTION. DATA lt_file TYPE sdokcntbins. DATA lv_len TYPE i. DATA ls_excel_data TYPE zzz_s_test_xls. ls_excel_data-shop = 'Березка'. ls_excel_data-manager = 'Иванов И.И.'. ls_excel_data-pricelist = VALUE zzz_t_price_list_test( ( name = 'HP Elitebook' price = '70000' waers = 'RUB' col = '1' ) ( name = 'HP Pavilion' price = '50000' waers = 'RUB' col = '5' ) ( name = 'DELL Latitude' price = '80000' waers = 'RUB' col = '3' ) ( name = 'Lenovo' price = '40000' waers = 'RUB' col = '0' ) ). CALL TRANSFORMATION zzz_test_excel_generate SOURCE maindata = ls_excel_data * pricelist = lt_pricelist RESULT XML DATA(lv_excel). CALL FUNCTION 'SCMS_XSTRING_TO_BINARY' EXPORTING buffer = lv_excel IMPORTING output_length = lv_len TABLES binary_tab = lt_file. cl_gui_frontend_services=>gui_download( EXPORTING bin_filesize = lv_len " File length for binary files filename = 'C:\Users\USER\Desktop\zip_example.xls' " Name of file filetype = 'BIN' " File type (ASCII, binary ...) CHANGING data_tab = lt_file " Transfer table EXCEPTIONS OTHERS = 1 ). IF sy-subrc <> 0. MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4. RETURN. ENDIF. |
Результат вызова программы: