<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> <si><t> </t></si> <si><t> </t></si> $ $ </sst>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> <si><t> </t></si> <si><t> </t></si> < > </sst>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"> %strings% </sst>
<sheetViews> <sheetView tabSelected="1" workbookViewId="0"> %attach% </sheetView> </sheetViews> <sheetFormatPr defaultRowHeight="15" x14ac:dyDescent="0.25"/> %colsize% <sheetData> %data% </sheetData> %filter%
-- , - v_blobsrc := lib_utils.get_blob_from_file('FILE_DIR', 'src_blank.xlsx');
/* : */ type tp_cell is record(address varchar2(15), style number, val varchar2(4000), lines number default 1); /* : */ type tp_row is table of tp_cell index by binary_integer; /* : () */ type tp_table is table of tp_row index by binary_integer; /* : */ type tp_string is table of varchar2(4000) index by binary_integer; type tp_number is table of number index by binary_integer;
file_build(i_content tp_table, i_filename varchar2, i_filter number default 0, i_attach number default 0);
/* ( Excel) */ function get_literal(i_number number) return varchar2 is begin -- if i_number < 1 or is_number(i_number) = false then return '#'; -- 1- elsif i_number > 0 and i_number < 29 then return chr(64 + i_number); -- 2- else return chr(64 + trunc(i_number / 28))||chr(64 + (i_number - (28 * trunc(i_number / 28)))); end if; end get_literal; /* : */ function is_number(i_char char) return boolean is begin if (to_number(i_char) = to_number(i_char)) then return true; end if; exception when others then return false; end is_number; /* */ function array_search(i_source tp_string, i_value varchar2) return number is begin for i in 1 .. i_source.count loop if i_value = i_source(i) then return i; end if; end loop; return -1; end array_search; /* "" ( 32767 ) CLOB- */ procedure clob_append(i_dest in out clob, i_src in varchar2, i_encode in varchar2 default 'utf8') is begin if i_src is not null then if i_dest is null then i_dest := to_clob(convert(i_src, i_encode)); else dbms_lob.write(i_dest, length(convert(i_src, i_encode)), length(i_dest) + 1, convert(i_src, i_encode)); end if; end if; end clob_append;
procedure build_file(i_content tp_table, i_filename varchar2, i_filter number default 0, i_attach number default 0) is v_blobsrc blob; -- BLOB v_blobres blob; -- BLOB c_namesrc constant varchar2(50) := 'src_blank.xlsx'; -- - v_stringarr tp_string; -- v_numarr tp_number; -- v_index number; -- v_clobmarkup clob; -- v_clobstring clob; -- sharedStrings.xml v_clobcolumns clob; -- c_letsize constant number := 3; -- 1 .. c_padding constant number := 1; -- v_rowcount number; -- - v_colcount number; -- - v_multiline number; -- v_filtertag varchar2(50); -- v_attachtag varchar2(150); -- begin /* */ for l_row in 1 .. i_content.count loop v_rowcount := l_row; -- DIMENSION /* , . , */ v_multiline := 1; for l_col in 1 .. i_content(l_row).count loop if i_content(l_row)(l_col).lines > v_multiline then v_multiline := i_content(l_row)(l_col).lines; end if; end loop; clob_append(v_clobmarkup, '<row r="'||l_row||'"'||case when v_multiline > 1 then ' ht="'||(15 * v_multiline)||'" customHeight="1"' else null end||'>'||chr(10)); /* */ for l_cells in 1 .. i_content(l_row).count loop v_colcount := l_cells; -- if i_content(l_row)(l_cells).val is null then clob_append(v_clobmarkup, '<cr="'||i_content(l_row)(l_cells).address||'" s="'||i_content(l_row)(l_cells).style||'"><v></v></c>'||chr(10)); else -- if is_number(i_content(l_row)(l_cells).val) then clob_append(v_clobmarkup, '<cr="'||i_content(l_row)(l_cells).address||'" s="'||i_content(l_row)(l_cells).style||'"><v>'||i_content(l_row)(l_cells).val||'</v></c>'||chr(10)); else /* : "-1" - , */ v_index := array_search(v_stringarr, i_content(l_row)(l_cells).val); if v_index = -1 then v_index := v_stringarr.count + 1; v_stringarr(v_index) := i_content(l_row)(l_cells).val; end if; -- -- clob_append(v_clobmarkup, '<cr="'||i_content(l_row)(l_cells).address||'" s="'||i_content(l_row)(l_cells).style||'" t="s"><v>'||(v_index - 1)||'</v></c>'||chr(10)); end if; end if; /* */ if v_numarr.count >= l_cells then if length(i_content(l_row)(l_cells).val) > v_numarr(l_cells) then v_numarr(l_cells) := length(i_content(l_row)(l_cells).val); end if; elsif v_numarr.count = l_cells - 1 then v_numarr(l_cells) := length(i_content(l_row)(l_cells).val); end if; end loop; -- clob_append(v_clobmarkup, chr(10)||'</row>'); end loop; -- clob_append(v_clobcolumns, '<cols>'); for l_cnt in 1 .. v_numarr.count loop clob_append(v_clobcolumns, '<col min="'||l_cnt||'" max="'||l_cnt||'" width="'||round((v_numarr(l_cnt) * c_letsize / 2) + c_padding)||'" style="1" customWidth="1"/>'); end loop; clob_append(v_clobcolumns, '</cols>'); -- for l_cnt in 1 .. v_stringarr.count loop clob_append(v_clobstring, '<si><t>'||v_stringarr(l_cnt)||'</t></si>'||chr(10)); end loop; /* - */ if i_filter = 1 then v_filtertag := '<autoFilter ref="A1:'||get_literal(v_colcount)||'1"/>'; end if; if i_attach = 1 then v_attachtag := '<pane ySplit="1" topLeftCell="A2" activePane="bottomLeft" state="frozen"/>'; end if; -- v_blobsrc := lib_utils.get_blob_from_file('FILE_DIR', c_namesrc); v_blobres := lib_utils.get_file_from_template(v_blobsrc, lib_utils.t_str_array('%colsize%', '%data%', '%strings%', '%filter%', '%attach%', '<dimension ref="A1:B2"/>'), lib_utils.t_str_array(v_clobcolumns, v_clobmarkup, v_clobstring, v_filtertag, v_attachtag, '<dimension ref="A1:'||get_literal(v_colcount)||v_rowcount||'"/>')); lib_utils.save_blob_to_file('FILE_DIR', i_filename, v_blobres); exception when others then dbms_output.put_line(' Excel: '||sqlerrm); end build_file;
Source: https://habr.com/ru/post/348450/
All Articles