Oracle读取excel数据
发布时间:2020-05-27 08:15:32 所属栏目:Oracle 来源:互联网
导读:本文给大家介绍Oracle读取excel数据的相关知识,本文介绍的非常详细,具有参考借鉴价值,感兴趣的朋友一起学习吧
推荐阅读:废话不多说了,直接给大家奔入主题了。 包体内容,包头: l_result,cache => true,dur => dbms_lob.call);
l_dest_offset := 1;
l_src_offset := 1;
dbms_lob.open(l_files,dbms_lob.lob_readonly);
dbms_lob.loadblobfromfile(l_result --dest_lob IN OUT NOCOPY BLOB,l_files
--src_lob IN BFILE,dbms_lob.lobmaxsize
--amount IN INTEGER,l_dest_offset
--dest_offset IN INTEGER := 1,l_src_offset
--src_offset IN INTEGER := 1
);
l_process_phase := 2;
dbms_lob.close(l_files);
l_process_phase := 99;
return l_result;
exception
when others then
if p_raise = /*xyg_pub_const_pkg.*/
c_true then
dbms_output.put_line('转换文件有异常错误!进度:' || l_process_phase);
raise;
/*xyg_pub_common_pkg.raise_error('-20001' --'ERR_DEFAULT_CODE',sqlerrm,'转换文件有异常错误!进度:' || l_process_phase);*/
--DBMS_OUTPUT.PUT_LINE ('THERE ARE SOME ERROR,PLEASE CONTACT WITH MIS');
else
--UTL_FILE.FCLOSE (L_FILEHANDLE);
return empty_blob();
end if;
end;
----------------------
------程序主体部分----
----------------------
function conver_excel_to_tab(p_document blob,p_raise in number default /*xyg_pub_const_pkg.*/ c_true)
return xyg_pub_data_upload_obj_tab
pipelined is
type tp_cell is record(
data_type varchar2(1),string_val varchar2(32767),number_val number,date_val date,blob_val blob);
type tp_row is table of tp_cell index by pls_integer;
type tp_rows is table of tp_row index by pls_integer;
type tp_sheet is record(
name varchar2(2000),rows tp_rows);
type tp_data is table of tp_sheet index by pls_integer;
t_data tp_data;
t_collection_base varchar2(32767);
t_collection_name varchar2(32767);
--type tp_2col is table of vc_arr2 index by pls_integer;
--t2 tp_2col;
l_round char(1) := 'Y';
l_process_phase number;
---xls:
type tp_sheet_rec is record(
name varchar2(32767),ind integer);
type tp_sheets is table of tp_sheet_rec index by pls_integer;
t_sheets tp_sheets;
t_sheet tp_sheet_rec;
--xlsx:
type tp_strings is table of varchar2(32767) index by pls_integer;
t_sheet_ids tp_strings;
t_sheet_names tp_strings;
-----------------
----XLS解析器----
-----------------
function g1(i pls_integer,r pls_integer,c pls_integer) return varchar2 is
l_return varchar2(4000);
begin
if l_round = 'Y' then
l_return := case
when t_data(i).rows(r).exists(c) then
coalesce(substr(t_data(i).rows(r)(c).string_val,4000),to_char(round(t_data(i).rows(r)(c).number_val,14 -
substr(to_char(t_data(i).rows(r)(c)
.number_val,'TME'),-3)),'TM9'),to_char(t_data(i).rows(r)(c).date_val,'yyyy-mm-dd hh24:mi:ss'))
end;
else
l_return := case
when t_data(i).rows(r).exists(c) then
coalesce(substr(t_data(i).rows(r)(c).string_val,to_char(t_data(i).rows(r)(c).number_val,'yyyy-mm-dd hh24:mi:ss'))
end;
end if;
return l_return;
--return case when t_data(i)(r).exists(c) then substr( t_data(i)(r)(c),4000 ) end;
end;
function parse_xls(p_document blob,p_sheets varchar2 := null,p_extra dbmsoutput_linesarray := null)
return tp_data is
t_cell tp_cell;
t_rows tp_rows;
t_data tp_data;
t_workbook blob;
t_ind integer;
t_sind integer;
t_len integer;
t_max_len integer;
t_cnt integer;
t_grbit raw(1);
t_biff5 boolean;
t_str varchar2(32767);
t_tmp raw(32767);
t_rec raw(32767);
t_date1904 boolean;
type tp_sst is table of varchar2(32767) index by pls_integer;
t_sst tp_sst;
type tp_date is table of boolean index by pls_integer;
t_xf_date tp_date;
t_fmt_date tp_date;
type tp_xf_fmt is table of pls_integer index by pls_integer;
t_xf_fmt tp_xf_fmt;
t_fmt varchar2(32767);
t_char_set varchar2(100) := 'WE8MSWIN1252';
t_c pls_integer;
t_type varchar2(1);
t_max_c pls_integer;
procedure read_unicode_string is
t_uni raw(32767);
begin
t_str := null;
while t_cnt > 0 loop
if utl_raw.bit_and(t_grbit,hextoraw('01')) = hextoraw('01') then
if (t_sind + t_cnt * 2 > utl_raw.length(t_rec) + 1 and
dbms_lob.substr(t_workbook,2,t_ind + t_len + 4) =
hextoraw('3C00')) then
t_str := t_str ||
utl_i18n.raw_to_char(utl_raw.substr(t_rec,t_sind),'AL16UTF16LE');
t_cnt := t_cnt -
utl_raw.length(utl_raw.substr(t_rec,t_sind)) / 2;
t_ind := t_ind + t_len + 4;
t_len := utl_raw.cast_to_binary_integer(dbms_lob.substr(t_workbook,t_ind + 2),utl_raw.little_endian);
t_grbit := dbms_lob.substr(t_workbook,t_ind + 4);
t_rec := dbms_lob.substr(t_workbook,t_len - 1,t_ind + 4 + 1);
t_sind := 1;
else
t_str := t_str ||
utl_i18n.raw_to_char(utl_raw.substr(t_rec,t_sind,t_cnt * 2),'AL16UTF16LE');
t_sind := t_sind + t_cnt * 2;
t_cnt := 0;
end if;
else
if (t_sind + t_cnt > utl_raw.length(t_rec) + 1 and
dbms_lob.substr(t_workbook,t_ind + t_len + 4) =
hextoraw('3C00')) then
t_tmp := utl_raw.substr(t_rec,t_sind);
t_cnt := t_cnt -
utl_raw.length(utl_raw.substr(t_rec,t_sind));
t_ind := t_ind + t_len + 4;
t_len := utl_raw.cast_to_binary_integer(dbms_lob.substr(t_workbook,t_ind + 4 + 1);
t_sind := 1;
else
t_tmp := utl_raw.substr(t_rec,t_cnt);
t_sind := t_sind + t_cnt;
t_cnt := 0;
end if;
t_uni := null;
for i in 1 .. utl_raw.length(t_tmp) loop
t_uni := utl_raw.concat(t_uni,utl_raw.substr(t_tmp,i,1),hextoraw('00'));
end loop;
t_str := t_str || utl_i18n.raw_to_char(t_uni,'AL16UTF16LE');
end if;
end loop;
end;
function rk2number(p_rk raw) return number is
begin
return case rawtohex(utl_raw.bit_and(utl_raw.substr(p_rk,'03')) when '02' then utl_raw.cast_to_binary_integer(utl_raw.bit_and(p_rk,'FCFFFFFF'),utl_raw.little_endian) / 4 when '03' then utl_raw.cast_to_binary_integer(utl_raw.bit_and(p_rk,utl_raw.little_endian) / 400 when '00' then utl_raw.cast_to_binary_double(utl_raw.concat('00000000',p_rk),utl_raw.little_endian) when '01' then utl_raw.cast_to_binary_double(utl_raw.concat('00000000',utl_raw.bit_and(p_rk,'FCFFFFFF')),utl_raw.little_endian) / 100 end;
end;
function num2date(p_num number) return date is
begin
if t_date1904 then
return to_date('01-01-1904','DD-MM-YYYY') + p_num;
end if;
return to_date('01-03-1900','DD-MM-YYYY') +(p_num - 61);
end;
procedure read_cfb(p_cf blob) is
t_header raw(512);
t_byte_order pls_integer;
t_encoding varchar2(30);
t_ssz pls_integer;
t_sssz pls_integer;
t_sectid pls_integer;
t_tmp_sectid t_sectid%type;
type tp_secids is table of t_sectid%type index by pls_integer;
t_msat tp_secids;
t_sat tp_secids;
t_ssat tp_secids;
t_sector raw(2048);
t_short_container blob;
t_stream blob;
t_len pls_integer;
t_name varchar2(32 char);
c_free_secid constant pls_integer := -1;
c_end_of_chain_secid constant pls_integer := -2;
c_sat_secid constant pls_integer := -3;
c_msat_secid constant pls_integer := -4;
c_dir_empty constant raw(1) := hextoraw('00');
c_dir_storage constant raw(1) := hextoraw('01');
c_dir_stream constant raw(1) := hextoraw('02');
c_dir_lock constant raw(1) := hextoraw('03');
c_dir_property constant raw(1) := hextoraw('04');
c_dir_root constant raw(1) := hextoraw('05');
begin
t_header := dbms_lob.substr(p_cf,512,1);
if (t_header is null or utl_raw.length(t_header) < 512 or
utl_raw.substr(t_header,8) != hextoraw('D0CF11E0A1B11AE1')) then
return;
end if;
t_byte_order := case
when utl_raw.substr(t_header,29,2) = hextoraw('FEFF') then
utl_raw.little_endian
else
utl_raw.big_endian
end;
if t_byte_order = utl_raw.little_endian then
t_encoding := 'AL16UTF16LE';
else
t_encoding := 'AL16UTF16';
end if;
t_ssz := power(2,utl_raw.cast_to_binary_integer(utl_raw.substr(t_header,31,2),t_byte_order));
t_sssz := power(2,33,t_byte_order));
for i in 0 .. 109 - 1 loop
t_sectid := utl_raw.cast_to_binary_integer(utl_raw.substr(t_header,77 +
i * 4,4),t_byte_order);
exit when t_sectid = c_free_secid;
t_msat(i) := t_sectid;
end loop;
t_sectid := utl_raw.cast_to_binary_integer(utl_raw.substr(t_header,69,t_byte_order);
while t_sectid != c_end_of_chain_secid loop
t_sector := dbms_lob.substr(p_cf,t_ssz,512 + t_ssz * t_sectid + 1);
for i in 0 .. t_ssz / 4 - 2 loop
t_msat(t_msat.count()) := utl_raw.cast_to_binary_integer(utl_raw.substr(t_sector,i * 4 + 1,t_byte_order);
end loop;
t_sectid := utl_raw.cast_to_binary_integer(utl_raw.substr(t_sector,-4,t_byte_order);
end loop;
for j in 0 .. t_msat.count() - 1 loop
t_sector := dbms_lob.substr(p_cf,512 + t_ssz * t_msat(j) + 1);
for i in 0 .. t_ssz / 4 - 1 loop
t_sat(t_sat.count()) := utl_raw.cast_to_binary_integer(utl_raw.substr(t_sector,t_byte_order);
end loop;
end loop;
t_sectid := utl_raw.cast_to_binary_integer(utl_raw.substr(t_header,61,512 + t_ssz * t_sectid + 1);
for i in 0 .. t_ssz / 4 - 1 loop
t_ssat(t_ssat.count()) := utl_raw.cast_to_binary_integer(utl_raw.substr(t_sector,t_byte_order);
end loop;
t_sectid := t_sat(t_sectid);
end loop;
t_sectid := utl_raw.cast_to_binary_integer(utl_raw.substr(t_header,49,512 + t_ssz * t_sectid + 1);
for i in 0 .. t_ssz / 128 - 1 loop
t_len := utl_raw.cast_to_binary_integer(utl_raw.substr(t_sector,i * 128 + 65,t_byte_order);
if t_len > 2 then
t_name := utl_i18n.raw_to_char(utl_raw.substr(t_sector,i * 128 + 1,t_len - 2),t_encoding);
end if;
case utl_raw.substr(t_sector,i * 128 + 67,1)
when c_dir_stream then
dbms_lob.createtemporary(t_stream,true);
t_tmp_sectid := utl_raw.cast_to_binary_integer(utl_raw.substr(t_sector,i * 128 + 117,t_byte_order);
t_len := utl_raw.cast_to_binary_integer(utl_raw.substr(t_sector,i * 128 + 121,t_byte_order);
if t_len >=
utl_raw.cast_to_binary_integer(utl_raw.substr(t_header,57,t_byte_order) then
while t_tmp_sectid != c_end_of_chain_secid loop
dbms_lob.append(t_stream,dbms_lob.substr(p_cf,512 +
t_ssz * t_tmp_sectid + 1));
t_tmp_sectid := t_sat(t_tmp_sectid);
end loop;
else
while t_tmp_sectid != c_end_of_chain_secid loop
dbms_lob.append(t_stream,dbms_lob.substr(t_short_container,t_sssz,t_sssz * t_tmp_sectid + 1));
t_tmp_sectid := t_ssat(t_tmp_sectid);
end loop;
end if;
dbms_lob.trim(t_stream,t_len);
if t_name = 'Workbook' then
t_workbook := t_stream;
end if;
if t_name = 'Book' then
t_workbook := t_stream;
end if;
when c_dir_root then
dbms_lob.createtemporary(t_short_container,t_byte_order);
while t_tmp_sectid != c_end_of_chain_secid loop
dbms_lob.append(t_short_container,512 + t_ssz * t_tmp_sectid + 1));
t_tmp_sectid := t_sat(t_tmp_sectid);
end loop;
else
null;
end case;
end loop;
t_sectid := t_sat(t_sectid);
end loop;
if dbms_lob.istemporary(t_short_container) = 1 then
dbms_lob.freetemporary(t_short_container);
end if;
if dbms_lob.istemporary(t_stream) = 1 then
dbms_lob.freetemporary(t_stream);
end if;
end;
begin
--my_log('parsing XLS');
read_cfb(p_document);
if t_workbook is null or dbms_lob.getlength(t_workbook) = 0 then
--my_log('No workbook file found');
raise_application_error(-20003,'Not a valid XLS-file',true);
end if;
t_ind := 1;
t_max_len := dbms_lob.getlength(t_workbook);
if (dbms_lob.substr(t_workbook,t_ind) = hextoraw('0908') and
dbms_lob.substr(t_workbook,t_ind + 4) in
(hextoraw('0005'),hextoraw('0006')) and
dbms_lob.substr(t_workbook,t_ind + 6) = hextoraw('0500')) then
t_biff5 := dbms_lob.substr(t_workbook,t_ind + 4) =
hextoraw('0005');
t_len := utl_raw.cast_to_binary_integer(dbms_lob.substr(t_workbook,utl_raw.little_endian);
t_ind := t_ind + t_len + 4;
loop
exit when t_ind >= t_max_len;
exit when dbms_lob.substr(t_workbook,t_ind) = hextoraw('0A00');
t_len := utl_raw.cast_to_binary_integer(dbms_lob.substr(t_workbook,utl_raw.little_endian);
if dbms_lob.substr(t_workbook,t_ind) = hextoraw('FC00') then
declare
t_run integer;
t_ext integer;
procedure add_cont(p_len pls_integer) is
begin
if (t_sind + p_len > utl_raw.length(t_rec) + 1 and
dbms_lob.substr(t_workbook,t_ind + t_len + 4) =
hextoraw('3C00')) then
t_ind := t_ind + t_len + 4;
t_len := utl_raw.cast_to_binary_integer(dbms_lob.substr(t_workbook,utl_raw.little_endian);
if t_sind <= utl_raw.length(t_rec) then
t_rec := utl_raw.concat(utl_raw.substr(t_rec,dbms_lob.substr(t_workbook,t_len,t_ind + 4));
else
t_rec := dbms_lob.substr(t_workbook,t_ind + 4);
end if;
t_sind := 1;
end if;
end;
begin
t_sind := 1;
t_rec := dbms_lob.substr(t_workbook,t_len - 8,t_ind + 12);
for j in 1 .. utl_raw.cast_to_binary_integer(dbms_lob.substr(t_workbook,4,t_ind + 8),utl_raw.little_endian) loop
add_cont(3);
t_cnt := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian);
t_sind := t_sind + 2;
t_grbit := utl_raw.substr(t_rec,1);
t_sind := t_sind + 1;
if utl_raw.bit_and(t_grbit,hextoraw('08')) =
hextoraw('08') then
add_cont(2);
t_run := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian);
t_sind := t_sind + 2;
else
t_run := 0;
end if;
if utl_raw.bit_and(t_grbit,hextoraw('04')) =
hextoraw('04') then
add_cont(4);
t_ext := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian);
if t_ext < 0 then
t_ext := t_ext + 4294967296;
end if;
t_sind := t_sind + 4;
else
t_ext := 0;
end if;
read_unicode_string;
t_sst(t_sst.count()) := t_str;
add_cont(t_run * 4 + t_ext);
t_sind := t_sind + t_run * 4 + t_ext;
end loop;
end;
elsif dbms_lob.substr(t_workbook,t_ind) = hextoraw('8500') then
t_rec := dbms_lob.substr(t_workbook,t_ind + 4);
if t_biff5 then
t_cnt := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,7,utl_raw.little_endian);
t_tmp := utl_raw.substr(t_rec,8,t_cnt);
t_sheet.name := utl_i18n.raw_to_char(t_tmp,t_char_set);
else
t_cnt := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,1));
t_grbit := utl_raw.substr(t_rec,1);
if utl_raw.bit_and(t_grbit,hextoraw('01')) = hextoraw('01') then
t_str := utl_raw.substr(t_rec,9,t_cnt * 2);
else
t_str := null;
t_tmp := utl_raw.substr(t_rec,t_cnt);
for i in 1 .. utl_raw.length(t_tmp) loop
t_str := utl_raw.concat(t_str,hextoraw('00'));
end loop;
end if;
t_sheet.name := utl_i18n.raw_to_char(t_str,'AL16UTF16LE');
end if;
t_sheet.ind := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian);
t_sheets(t_sheets.count()) := t_sheet;
elsif dbms_lob.substr(t_workbook,t_ind) = hextoraw('2200') then
t_date1904 := dbms_lob.substr(t_workbook,t_ind + 4) =
hextoraw('0100');
elsif dbms_lob.substr(t_workbook,t_ind) = hextoraw('1E04') then
t_rec := dbms_lob.substr(t_workbook,3,t_cnt);
t_fmt := utl_i18n.raw_to_char(t_tmp,utl_raw.little_endian);
t_grbit := utl_raw.substr(t_rec,5,6,hextoraw('00'));
end loop;
end if;
t_fmt := utl_i18n.raw_to_char(t_str,'AL16UTF16LE');
end if;
t_fmt_date(utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian)) := (instr(t_fmt,'dd') > 0 or
instr(t_fmt,'mm') > 0 or
instr(t_fmt,'yy') > 0);
elsif dbms_lob.substr(t_workbook,t_ind) = hextoraw('E000') then
t_rec := dbms_lob.substr(t_workbook,t_ind + 4);
t_xf_fmt(t_xf_fmt.count()) := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian);
elsif dbms_lob.substr(t_workbook,t_ind) = hextoraw('4200') then
t_rec := dbms_lob.substr(t_workbook,t_ind + 4);
if (rawtohex(t_rec) in ('1027','0080') and
nls_charset_id('WE8MACROMAN8') is not null) then
t_char_set := 'WE8MACROMAN8';
end if;
end if;
t_ind := t_ind + t_len + 4;
end loop;
t_fmt_date(14) := true;
t_fmt_date(15) := true;
t_fmt_date(16) := true;
t_fmt_date(17) := true;
t_fmt_date(22) := true;
for i in 0 .. t_xf_fmt.count() - 1 loop
t_xf_date(i) := t_fmt_date.exists(t_xf_fmt(i)) and
t_fmt_date(t_xf_fmt(i));
end loop;
end if;
for s in 0 .. t_sheets.count - 1 loop
t_ind := t_sheets(s).ind + 1;
if (dbms_lob.substr(t_workbook,t_ind + 4) = hextoraw('0006') and
dbms_lob.substr(t_workbook,t_ind + 6) = hextoraw('1000') and
(p_sheets is null or
instr(':' || p_sheets || ':',':' || to_char(s + 1) || ':') > 0 or
instr(':' || p_sheets || ':',':' || t_sheets(s).name || ':') > 0)) then
t_max_c := 0;
t_rows.delete;
t_data(t_data.count + 1).name := t_sheets(s).name;
--my_log('read ' || t_sheets(s).name);
t_len := utl_raw.cast_to_binary_integer(dbms_lob.substr(t_workbook,t_ind) = hextoraw('0A00');
t_cell := null;
t_len := utl_raw.cast_to_binary_integer(dbms_lob.substr(t_workbook,t_ind) = hextoraw('7E02') then
t_rec := dbms_lob.substr(t_workbook,t_ind + 4);
if t_xf_date(utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian)) then
t_cell.data_type := 'D';
t_cell.date_val := num2date(rk2number(utl_raw.substr(t_rec,4)));
else
t_cell.data_type := 'N';
t_cell.number_val := rk2number(utl_raw.substr(t_rec,4));
end if;
t_c := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian) + 1;
t_max_c := greatest(t_max_c,t_c);
t_rows(utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian) + 1)(t_c) := t_cell;
elsif dbms_lob.substr(t_workbook,t_ind) = hextoraw('0302') then
t_rec := dbms_lob.substr(t_workbook,utl_raw.little_endian)) then
t_cell.data_type := 'D';
t_cell.date_val := num2date(utl_raw.cast_to_binary_double(utl_raw.substr(t_rec,8),utl_raw.little_endian));
else
t_cell.data_type := 'N';
t_cell.number_val := utl_raw.cast_to_binary_double(utl_raw.substr(t_rec,utl_raw.little_endian);
end if;
t_c := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,t_ind) = hextoraw('0600') then
t_rec := dbms_lob.substr(t_workbook,t_ind + 4);
if (rawtohex(utl_raw.substr(t_rec,1)) not in
('00','01','02','03') or
utl_raw.substr(t_rec,13,2) != hextoraw('FFFF')) then
if t_xf_date(utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian) + 1)(t_c) := t_cell;
else
case rawtohex(utl_raw.substr(t_rec,1))
when '01' then
t_cell.data_type := 'S';
t_cell.string_val := case
rawtohex(utl_raw.substr(t_rec,1))
when '00' then
'FALSE'
when '01' then
'TRUE'
end;
t_c := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian) + 1)(t_c) := t_cell;
when '02' then
null;
when '00' then
if dbms_lob.substr(t_workbook,t_ind + t_len + 4) =
hextoraw('0702') then
declare
t_row pls_integer := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian) + 1;
t_col pls_integer := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian) + 1;
begin
t_ind := t_ind + t_len + 4;
t_len := utl_raw.cast_to_binary_integer(dbms_lob.substr(t_workbook,utl_raw.little_endian);
t_rec := dbms_lob.substr(t_workbook,t_ind + 4);
t_cnt := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian);
t_sind := 4;
t_cell.data_type := 'S';
if t_biff5 then
t_tmp := utl_raw.substr(t_rec,t_cnt);
t_cell.string_val := utl_i18n.raw_to_char(t_tmp,t_char_set);
else
t_grbit := dbms_lob.substr(t_rec,3);
read_unicode_string;
t_cell.string_val := t_str;
end if;
t_max_c := greatest(t_max_c,t_col);
t_rows(t_row)(t_col) := t_cell;
end;
end if;
else
t_cell.data_type := 'S';
t_cell.string_val := '';
t_c := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian) + 1)(t_c) := t_cell;
end case;
end if;
elsif dbms_lob.substr(t_workbook,t_ind) = hextoraw('0402') then
t_rec := dbms_lob.substr(t_workbook,t_ind + 4);
if t_biff5 then
t_cell.data_type := 'S';
t_cnt := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian);
if t_cnt = 0 then
t_cell.string_val := null;
else
t_tmp := utl_raw.substr(t_rec,t_char_set);
end if;
t_c := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian) + 1)(t_c) := t_cell;
end if;
elsif dbms_lob.substr(t_workbook,t_ind) = hextoraw('D600') then
t_rec := dbms_lob.substr(t_workbook,t_cnt);
t_cell.data_type := 'S';
t_cell.string_val := utl_i18n.raw_to_char(t_tmp,t_char_set);
t_c := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,t_ind) = hextoraw('FD00') then
t_rec := dbms_lob.substr(t_workbook,t_ind + 4);
t_cell.data_type := 'S';
t_c := utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,t_c);
t_cell.string_val := t_sst(utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian));
t_rows(utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,t_ind) = hextoraw('BD00') then
t_rec := dbms_lob.substr(t_workbook,utl_raw.little_endian);
for i in utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian) .. utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,-2,utl_raw.little_endian) loop
t_tmp := utl_raw.substr(t_rec,5 + 6 * (i - t_cnt),6);
if t_xf_date(utl_raw.cast_to_binary_integer(utl_raw.substr(t_tmp,utl_raw.little_endian)) then
t_cell.data_type := 'D';
t_cell.date_val := num2date(rk2number(utl_raw.substr(t_tmp,4)));
else
t_cell.data_type := 'N';
t_cell.number_val := rk2number(utl_raw.substr(t_tmp,4));
end if;
t_max_c := greatest(t_max_c,i + 1);
t_rows(utl_raw.cast_to_binary_integer(utl_raw.substr(t_rec,utl_raw.little_endian) + 1)(i + 1) := t_cell;
end loop;
end if;
t_ind := t_ind + t_len + 4;
end loop;
if t_rows.count > 0 then
t_c := t_rows(t_rows.last).first;
t_type := t_rows(t_rows.last)(t_c).data_type;
for r in 1 .. t_rows.last - 1 loop
if not t_rows.exists(r) then
t_rows(r)(t_c).data_type := t_type;
end if;
end loop;
if t_rows.count > 1 then
for c in 1 .. t_max_c loop
t_type := null;
for r in 2 .. t_rows.last loop
if t_rows(r).exists(c) then
t_type := t_rows(r)(c).data_type;
exit;
end if;
end loop;
if t_type is null then
if t_rows(1).exists(c) then
t_type := t_rows(1)(c).data_type;
else
t_type := 'S';
end if;
end if;
for r in 1 .. t_rows.last loop
if not t_rows(r).exists(c) then
t_rows(r)(c).data_type := t_type;
end if;
end loop;
end loop;
else
for c in 1 .. t_max_c loop
if not t_rows(1).exists(c) then
t_rows(1)(c).data_type := 'S';
end if;
end loop;
end if;
end if;
t_data(t_data.count).rows := t_rows;
end if;
end loop;
return t_data;
end;
-----------------
----XLSX解析器----
-----------------
function g2(i pls_integer,4000 ) end;
end;
function blob2node(p_blob blob) return dbms_xmldom.domnode is
begin
if p_blob is null or dbms_lob.getlength(p_blob) = 0 then
return null;
end if;
return dbms_xmldom.makenode(dbms_xmldom.getdocumentelement(dbms_xmldom.newdomdocument(xmltype(p_blob,nls_charset_id('AL32UTF8')))));
exception
when others then
declare
t_nd dbms_xmldom.domnode;
t_clob clob;
t_dest_offset integer;
t_src_offset integer;
t_lang_context number := dbms_lob.default_lang_ctx;
t_warning integer;
begin
dbms_lob.createtemporary(t_clob,true);
t_dest_offset := 1;
t_src_offset := 1;
dbms_lob.converttoclob(t_clob,p_blob,dbms_lob.lobmaxsize,t_dest_offset,t_src_offset,nls_charset_id('AL32UTF8'),t_lang_context,t_warning);
t_nd := dbms_xmldom.makenode(dbms_xmldom.getdocumentelement(dbms_xmldom.newdomdocument(t_clob)));
dbms_lob.freetemporary(t_clob);
return t_nd;
end;
end;
function blob2num(p_blob blob,p_len integer,p_pos integer)
return number is
begin
return utl_raw.cast_to_binary_integer(dbms_lob.substr(p_blob,p_len,p_pos),utl_raw.little_endian);
end;
function little_endian(p_big number,p_bytes pls_integer := 4) return raw is
begin
return utl_raw.substr(utl_raw.cast_from_binary_integer(p_big,utl_raw.little_endian),p_bytes);
end;
function col_alfan(p_col varchar2) return pls_integer is
begin
return ascii(substr(p_col,-1)) - 64 + nvl((ascii(substr(p_col,1)) - 64) * 26,0) + nvl((ascii(substr(p_col,-3,1)) - 64) * 676,0);
end;
function get_file(p_zipped_blob blob,p_file_name varchar2) return blob is
t_tmp blob;
t_ind integer;
t_hd_ind integer;
t_fl_ind integer;
t_encoding varchar2(10);
t_len integer;
begin
t_ind := dbms_lob.getlength(p_zipped_blob) - 21;
loop
exit when t_ind < 1 or dbms_lob.substr(p_zipped_blob,t_ind) = hextoraw('504B0506');
t_ind := t_ind - 1;
end loop;
if t_ind <= 0 then
return null;
end if;
t_hd_ind := blob2num(p_zipped_blob,t_ind + 16) + 1;
for i in 1 .. blob2num(p_zipped_blob,t_ind + 8) loop
if utl_raw.bit_and(dbms_lob.substr(p_zipped_blob,t_hd_ind + 9),hextoraw('08')) = hextoraw('08') then
t_encoding := 'AL32UTF8';
else
t_encoding := 'US8PC437';
end if;
if p_file_name =
utl_i18n.raw_to_char(dbms_lob.substr(p_zipped_blob,blob2num(p_zipped_blob,t_hd_ind + 28),t_hd_ind + 46),t_encoding) then
t_len := blob2num(p_zipped_blob,t_hd_ind + 24);
if t_len = 0 then
if substr(p_file_name,-1) in ('/','') then
return null;
else
return empty_blob();
end if;
end if;
if dbms_lob.substr(p_zipped_blob,t_hd_ind + 10) =
hextoraw('0800') then
t_fl_ind := blob2num(p_zipped_blob,t_hd_ind + 42);
t_tmp := hextoraw('1F8B0800000000000003');
dbms_lob.copy(t_tmp,p_zipped_blob,t_hd_ind + 20),11,t_fl_ind + 31 +
blob2num(p_zipped_blob,t_fl_ind + 27) +
blob2num(p_zipped_blob,t_fl_ind + 29));
dbms_lob.append(t_tmp,utl_raw.concat(dbms_lob.substr(p_zipped_blob,t_hd_ind + 16),little_endian(t_len)));
return utl_compress.lz_uncompress(t_tmp);
end if;
if dbms_lob.substr(p_zipped_blob,t_hd_ind + 10) =
hextoraw('0000') then
t_fl_ind := blob2num(p_zipped_blob,t_hd_ind + 42);
dbms_lob.createtemporary(t_tmp,true);
dbms_lob.copy(t_tmp,t_fl_ind + 29));
return t_tmp;
end if;
end if;
t_hd_ind := t_hd_ind + 46 +
blob2num(p_zipped_blob,t_hd_ind + 28) +
blob2num(p_zipped_blob,t_hd_ind + 30) +
blob2num(p_zipped_blob,t_hd_ind + 32);
end loop;
return null;
end;
function parse_xlsx(p_doc blob,p_extra dbmsoutput_linesarray := null)
return tp_data is
t_rows tp_rows;
t_data tp_data;
t_date1904 boolean;
type tp_date is table of boolean index by pls_integer;
t_xf_date tp_date;
t_numfmt_date tp_date;
t_strings tp_strings;
t_r varchar2(32767);
t_s varchar2(32767);
t_t varchar2(32767);
t_val varchar2(32767);
t_nr number;
t_x pls_integer;
t_xx pls_integer;
t_c pls_integer;
t_sc pls_integer;
t_rr pls_integer;
t_ns varchar2(200) := 'xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"';
t_nd dbms_xmldom.domnode;
t_nd2 dbms_xmldom.domnode;
t_nl dbms_xmldom.domnodelist;
t_nl2 dbms_xmldom.domnodelist;
t_nl3 dbms_xmldom.domnodelist;
t_type varchar2(1);
t_max_c pls_integer;
begin
--my_log('parsing XLSX');
t_nd := blob2node(get_file(p_doc,'xl/workbook.xml'));
t_date1904 := lower(dbms_xslprocessor.valueof(t_nd,'/workbook/workbookPr/@date1904',t_ns)) in ('true','1');
t_nl := dbms_xslprocessor.selectnodes(t_nd,'/workbook/sheets/sheet',t_ns);
for i in 0 .. dbms_xmldom.getlength(t_nl) - 1 loop
t_sheet_ids(i + 1) := dbms_xslprocessor.valueof(dbms_xmldom.item(t_nl,i),'@r:id','xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"');
t_sheet_names(i + 1) := dbms_xslprocessor.valueof(dbms_xmldom.item(t_nl,'@name');
end loop;
dbms_xmldom.freenode(t_nd);
t_nd := blob2node(get_file(p_doc,'xl/styles.xml'));
t_nl := dbms_xslprocessor.selectnodes(t_nd,'/styleSheet/numFmts/numFmt',t_ns);
for i in 0 .. dbms_xmldom.getlength(t_nl) - 1 loop
t_val := dbms_xslprocessor.valueof(dbms_xmldom.item(t_nl,'@formatCode');
if (instr(t_val,'dd') > 0 or instr(t_val,'mm') > 0 or
instr(t_val,'yy') > 0) then
t_numfmt_date(dbms_xslprocessor.valueof(dbms_xmldom.item(t_nl,'@numFmtId')) := true;
end if;
end loop;
t_numfmt_date(14) := true;
t_numfmt_date(15) := true;
t_numfmt_date(16) := true;
t_numfmt_date(17) := true;
t_numfmt_date(22) := true;
t_nl := dbms_xslprocessor.selectnodes(t_nd,'/styleSheet/cellXfs/xf/@numFmtId',t_ns);
for i in 0 .. dbms_xmldom.getlength(t_nl) - 1 loop
t_xf_date(i) := t_numfmt_date.exists(dbms_xmldom.getnodevalue(dbms_xmldom.item(t_nl,i)));
end loop;
dbms_xmldom.freenode(t_nd);
t_nd := blob2node(get_file(p_doc,'xl/sharedStrings.xml'));
if not dbms_xmldom.isnull(t_nd) then
t_x := 0;
t_xx := 10000;
loop
t_nl := dbms_xslprocessor.selectnodes(t_nd,'/sst/si[position()>="' ||
to_char(t_x * t_xx + 1) ||
'" and position()<="' ||
to_char((t_x + 1) * t_xx) || '"]',t_ns);
exit when dbms_xmldom.getlength(t_nl) = 0;
t_x := t_x + 1;
for i in 0 .. dbms_xmldom.getlength(t_nl) - 1 loop
t_sc := t_strings.count;
t_strings(t_sc) := dbms_xslprocessor.valueof(dbms_xmldom.item(t_nl,'.');
if t_strings(t_sc) is null then
t_strings(t_sc) := dbms_xslprocessor.valueof(dbms_xmldom.item(t_nl,'*/text()');
if t_strings(t_sc) is null then
t_nl2 := dbms_xslprocessor.selectnodes(dbms_xmldom.item(t_nl,'r/t/text()');
for j in 0 .. dbms_xmldom.getlength(t_nl2) - 1 loop
t_strings(t_sc) := t_strings(t_sc) ||
dbms_xmldom.getnodevalue(dbms_xmldom.item(t_nl2,j));
end loop;
end if;
end if;
end loop;
end loop;
end if;
t_nd2 := blob2node(get_file(p_doc,'xl/_rels/workbook.xml.rels'));
for i in 1 .. t_sheet_ids.count loop
if (p_sheets is null or
instr(':' || p_sheets || ':',':' || to_char(i) || ':') > 0 or
instr(':' || p_sheets || ':',':' || t_sheet_names(i) || ':') > 0) then
--跟踪日志
--p_ins_log(t_sheet_names(i));
t_max_c := 0;
t_rows.delete;
t_data(t_data.count + 1).name := t_sheet_names(i);
--my_log('read ' || t_sheet_names(i));
t_val := dbms_xslprocessor.valueof(t_nd2,'/Relationships/Relationship[@Id="' ||
t_sheet_ids(i) || '"]/@Target','xmlns="http://schemas.openxmlformats.org/package/2006/relationships"');
t_nd := blob2node(get_file(p_doc,'xl/' || t_val));
t_x := 0;
t_xx := 10000;
loop
t_nl3 := dbms_xslprocessor.selectnodes(t_nd,'/worksheet/sheetData/row[position()>="' ||
to_char(t_x * t_xx + 1) ||
'" and position()<="' ||
to_char((t_x + 1) * t_xx) || '"]');
exit when dbms_xmldom.getlength(t_nl3) = 0;
t_x := t_x + 1;
for r in 0 .. dbms_xmldom.getlength(t_nl3) - 1 loop
t_nl2 := dbms_xslprocessor.selectnodes(dbms_xmldom.item(t_nl3,r),'c[v]');
for j in 0 .. dbms_xmldom.getlength(t_nl2) - 1 loop
t_r := dbms_xslprocessor.valueof(dbms_xmldom.item(t_nl2,j),'@r',t_ns);
t_rr := ltrim(t_r,rtrim(t_r,'0123456789'));
t_c := col_alfan(rtrim(t_r,'0123456789'));
t_max_c := greatest(t_max_c,t_c);
t_val := dbms_xslprocessor.valueof(dbms_xmldom.item(t_nl2,'v');
t_t := dbms_xslprocessor.valueof(dbms_xmldom.item(t_nl2,'@t');
if t_t = 's' then
if t_val is not null then
t_rows(t_rr)(t_c).data_type := 'S';
t_rows(t_rr)(t_c).string_val := t_strings(to_number(t_val));
end if;
elsif t_t in ('str','inlineStr','e') then
if t_val is not null then
t_rows(t_rr)(t_c).data_type := 'S';
t_rows(t_rr)(t_c).string_val := t_val;
end if;
else
t_nr := to_number(t_val,case
when instr(t_val,'E') = 0 then
translate(t_val,'.012345678,-+','D999999999')
else
translate(substr(t_val,instr(t_val,'E') - 1),'D999999999') || 'EEEE'
end,'NLS_NUMERIC_CHARACTERS=.,');
t_s := dbms_xslprocessor.valueof(dbms_xmldom.item(t_nl2,'@s');
if t_s is not null and t_xf_date.exists(to_number(t_s)) and
t_xf_date(to_number(t_s)) then
t_rows(t_rr)(t_c).data_type := 'D';
if t_date1904 then
t_rows(t_rr)(t_c).date_val := to_date('01-01-1904','DD-MM-YYYY') + t_nr;
else
t_rows(t_rr)(t_c).date_val := to_date('01-03-1900','DD-MM-YYYY') +
(t_nr - 61);
end if;
else
t_rows(t_rr)(t_c).data_type := 'N';
t_rows(t_rr)(t_c).number_val := t_nr;
end if;
end if;
end loop;
end loop;
end loop;
dbms_xmldom.freenode(t_nd);
if t_rows.count > 0 then
t_c := t_rows(t_rows.last).first;
t_type := t_rows(t_rows.last)(t_c).data_type;
for r in 1 .. t_rows.last - 1 loop
if not t_rows.exists(r) then
t_rows(r)(t_c).data_type := t_type;
end if;
end loop;
if t_rows.count > 1 then
for c in 1 .. t_max_c loop
t_type := null;
for r in 2 .. t_rows.last loop
if t_rows(r).exists(c) then
t_type := t_rows(r)(c).data_type;
exit;
end if;
end loop;
if t_type is null then
if t_rows(1).exists(c) then
t_type := t_rows(1)(c).data_type;
else
t_type := 'S';
end if;
end if;
for r in 1 .. t_rows.last loop
if not t_rows(r).exists(c) then
t_rows(r)(c).data_type := t_type;
end if;
end loop;
end loop;
else
for c in 1 .. t_max_c loop
if not t_rows(1).exists(c) then
t_rows(1)(c).data_type := 'S';
end if;
end loop;
end if;
end if;
t_data(t_data.count).rows := t_rows;
end if;
end loop;
dbms_xmldom.freenode(t_nd2);
return t_data;
end;
begin
if dbms_lob.substr(p_document,1) = hextoraw('D0CF11E0A1B11AE1') then
--dbms_output.put_line( 'parsing XLS' );
--t_what := 'XLS-file';
--t_collection_base := :col_name;
l_process_phase := 0;
t_data := parse_xls(p_document,p_sheets);
l_process_phase := 10;
--DBMS_OUTPUT.PUT_LINE('parsed,' || t_data.count || ' sheets found');
--my_log('moving to Collection(s)');
--apex_collection.create_or_truncate_collection(t_collection_base ||'_$MAP');
for i in 1 .. t_data.count loop
--t_collection_name := t_collection_base || to_char(nullif(i,1));
--my_log('moving sheet ' || i || ': ' || t_data(i).name || ' to ' ||t_collection_name);
/*
apex_collection.add_member(t_collection_base || '_$MAP',p_c001 => t_data(i).name,p_c002 => t_collection_name,p_n001 => i);
apex_collection.create_or_truncate_collection(t_collection_name);*/
if t_data(i).rows.count() > 0 then
--t2.delete;
--DBMS_OUTPUT.PUT_LINE('t_data(i).rows.count():' || t_data(i).rows.count());
--DBMS_OUTPUT.PUT_LINE('t_sheets(i).name:' || t_sheets(i-1).name);
for r in 1 .. t_data(i).rows.last loop
if t_data(i).rows.exists(r) then
pipe row(xyg_pub_data_upload_obj('EXCEL-XLS' --P_SOURCE_TYPE,t_sheets(i - 1).name
--P_BATCH_CODE,null
--P_BATCH_NAME,r,g1(i,3),5),6),7),9),10),11),12),13),14),15),16),17),18),19),20),21),22),23),24),25),26),27),28),29),30),null));
else
--t2(1)(r) := ''
null;
end if;
end loop;
end if;
end loop;
elsif dbms_lob.substr(p_document,1) = hextoraw('504B0304') then
--log( 'parsing XLSX' );
--t_what := 'XLSX-file';
--t_collection_base := :col_name;
t_data := parse_xlsx(p_document,p_sheets);
--my_log('parsed,' || t_data.count || ' sheets found');
--my_log('moving to Collection(s)');
--apex_collection.create_or_truncate_collection(t_collection_base ||'_$MAP');
for i in 1 .. t_data.count loop
/*
t_collection_name := t_collection_base || to_char(nullif(i,1));
my_log('moving sheet ' || i || ': ' || t_data(i).name || ' to ' ||t_collection_name);
apex_collection.add_member(t_collection_base || '_$MAP',p_n001 => i);
apex_collection.create_or_truncate_collection(t_collection_name);*/
if t_data(i).rows.count() > 0 then
--t2.delete;
for r in 1 .. t_data(i).rows.last loop
if t_data(i).rows.exists(r) then
pipe row(xyg_pub_data_upload_obj('EXCEL-XLSX' --P_SOURCE_TYPE,t_sheet_names(i)
--P_BATCH_CODE,g2(i,null));
else
--t2(1)(r) := '';
null;
end if;
end loop;
end if;
end loop;
--RETURN CONVER_XLSX_TO_TAB(P_DOCUMENT,P_SHEETS,P_RAISE);
else
if p_raise = /*xyg_pub_const_pkg.*/
c_true then
l_process_phase := 97;
raise no_data_found;
else
l_process_phase := 98;
null;
end if;
end if; l_process_phase := 99;
return;
exception
when others then
if p_raise = /*xyg_pub_const_pkg.*/
c_true then
--DBMS_OUTPUT.PUT_LINE (R_LINE || '-' || V_PROCESS_MESSAGE);
/*XYG_PUB_COMMON_PKG.RAISE_ERROR (
'-20001' --'ERR_DEFAULT_CODE',SQLERRM,'ERROR RAISE!程序进度:' || L_PROCESS_PHASE
);*/
dbms_output.put_line('程序进度:' || l_process_phase);
raise;
else
return;
--return -1
end if;
end;
end xyg_pub_data_upload_pkg;
(编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
