diff --git a/funcext/TSOffice/TOfficeObj.tsf b/funcext/TSOffice/TOfficeObj.tsf index eee6167..87c4dae 100644 --- a/funcext/TSOffice/TOfficeObj.tsf +++ b/funcext/TSOffice/TOfficeObj.tsf @@ -1,4 +1,4 @@ -// Version 1.5.9 +// Version 1.6.0 Function TOfficeObj(n); Begin case lowercase(n) of diff --git a/funcext/TSOffice/TSDocxFile.tsf b/funcext/TSOffice/TSDocxFile.tsf index dbe1134..60a4142 100644 --- a/funcext/TSOffice/TSDocxFile.tsf +++ b/funcext/TSOffice/TSDocxFile.tsf @@ -1,4 +1,4 @@ -// Version 1.5.9 +// Version 1.6.0 Type TSDocxFile = Class ///Version: V1.0 2022-09-20 ///适用于 Microsoft Word docx格式文件 diff --git a/funcext/TSOffice/TSXlsxFile.tsf b/funcext/TSOffice/TSXlsxFile.tsf index 1532cb3..c3636aa 100644 --- a/funcext/TSOffice/TSXlsxFile.tsf +++ b/funcext/TSOffice/TSXlsxFile.tsf @@ -1,4 +1,4 @@ -// Version 1.5.9 +// Version 1.6.0 Type TSXlsxFile = Class ///Version: V1.0 2022-08-08 ///适用于 Microsoft Excel? 2007 及以上版本创建的电子表格文档。支持 XLSX / XLSM / XLTM / XLTX 等多种文档格式。 @@ -334,9 +334,11 @@ Type TSXlsxFile = Class colNum ++; End; for i:=0 to length(data)-1 do Begin - for j:=0 to length(data[i])-1 do Begin + j := 0; + for k, v in data[i] do Begin [err, cell] := CoordinatesToCellName(colNum + j, rowNum + i); - ret := SetCellValue(sheet, cell, data[i][j]); + j++; + ret := SetCellValue(sheet, cell, v); if not ret then return array(1, "error") End; End; diff --git a/funcext/TSOffice/worksheet/xlsxWorkBook.tsf b/funcext/TSOffice/worksheet/xlsxWorkBook.tsf index 6118a6b..1e36bf7 100644 --- a/funcext/TSOffice/worksheet/xlsxWorkBook.tsf +++ b/funcext/TSOffice/worksheet/xlsxWorkBook.tsf @@ -245,7 +245,22 @@ Type xlsxWorkBook = Class Begin //设置docProps/app.xml app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app')); - vector := class(TSXml).GetNode(app, 'Properties/TitlesOfParts/vt:vector'); + properties_node := app.FirstChildElement('Properties'); + // HeadingPairs + variant_node := class(TSXml).GetNode(properties_node, 'HeadingPairs/vt:vector/vt:variant'); + while ifObj(variant_node) do + begin + vt_node := variant_node.FirstChildElement('vt:i4'); + if ifObj(vt_node) then + begin + vt_node.SetValue(length(sheetNames_) + 1); + break; + end + variant_node := variant_node.NextElement(); + end + + // TitlesOfParts + vector := class(TSXml).GetNode(properties_node, 'TitlesOfParts/vt:vector'); vector.SetAttribute('size', length(sheetNames_) + 1); vector.InsertEndChild('element', 'vt:lpstr', sheet); End; @@ -257,6 +272,64 @@ Type xlsxWorkBook = Class class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType')); End; + Function insertWorkbookSheet(targetSheetName, newSheetName, sheetId, rId, direction); + Begin + workbook := GetXmlFileObj('xl/workbook.xml'); + node := class(TSXml).GetNode(workbook, 'workbook/sheets'); + sheet_node := node.FirstChildElement('sheet'); + while ifObj(sheet_node) do + begin + if sheet_node.GetAttribute('name') = targetSheetName then + begin + if direction = "after" then + sheet_node := node.InsertAfterChild(sheet_node, 'element', 'sheet'); + else + sheet_node := node.InsertBeforeChild(sheet_node, 'element', 'sheet'); + sheet_node.SetAttribute('name', newSheetName); + sheet_node.SetAttribute('sheetId', sheetId); + sheet_node.SetAttribute('r:id', rid); + break; + end + sheet_node := sheet_node.NextElement(); + end + End; + + Function insertDocPropsApp(targetSheetName, newSheetName, direction); + Begin + //设置docProps/app.xml + app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app')); + properties_node := app.FirstChildElement('Properties'); + // HeadingPairs + variant_node := class(TSXml).GetNode(properties_node, 'HeadingPairs/vt:vector/vt:variant'); + while ifObj(variant_node) do + begin + vt_node := variant_node.FirstChildElement('vt:i4'); + if ifObj(vt_node) then + begin + vt_node.SetValue(length(sheetNames_) + 1); + break; + end + variant_node := variant_node.NextElement(); + end + + // TitlesOfParts + vector := class(TSXml).GetNode(properties_node, 'TitlesOfParts/vt:vector'); + vector.SetAttribute('size', length(sheetNames_) + 1); + lpstr := vector.FirstChildElement('vt:lpstr'); + while ifObj(lpstr) do + begin + if LowerCase(lpstr.GetText()) = LowerCase(targetSheetName) then + begin + if direction = 'after' then + lpstr := vector.InsertAfterChild(lpstr, 'element', 'vt:lpstr'); + else + lpstr := vector.InsertBeforeChild(lpstr, 'element', 'vt:lpstr'); + lpstr.SetValue(newSheetName); + break; + end + lpstr := lpstr.NextElement(); + end + End; Function NewSheet(sourceSheet, destSheet);overload; Begin @@ -265,60 +338,12 @@ Type xlsxWorkBook = Class sname := LowerCase(sourceSheet); if not ifint(sheetIndexMap_[ sname ]) then return 'sourceSheet does not exists'; - //添加文件xl/worksheets/sheetN.xml - sheetId := vselect maxof(['sheetId']) from sheetNames_ end; - sheetId := integer(sheetId) + 1; fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml'; - zipfile_.Add(fname, class(TSXml).XmlHeader() + class(TSXml).GetTemplate('sheet1')); - - //设置 workbook.xml.rels - rid := getWorkbookRelsRid(); - workbook_rels := GetXmlFileObj('xl/_rels/workbook.xml.rels'); - rels := workbook_rels.FirstChildElement('Relationships').InsertEndChild('element', 'Relationship'); - rels.SetAttribute('Target', getTarget( sheetsCount_ + 1)); - rels.SetAttribute('Type', class(TSXml).GetTemplate('RelationshipWorkSheet')); - rels.SetAttribute('Id', rid); - //workbook_rels.Print; - - //设置 xl/workbook.xml - workbook := GetXmlFileObj('xl/workbook.xml'); - node := workbook.FirstChildElement('workbook').FirstChildElement('sheets'); - sheet_node := node.FirstChildElement('sheet'); - while ifObj(sheet_node) do - begin - if sheet_node.GetAttribute('name') = sourceSheet then - begin - sheet_node := node.InsertAfterChild(sheet_node, 'element', 'sheet'); - sheet_node.SetAttribute('name', destSheet); - sheet_node.SetAttribute('sheetId', sheetId); - sheet_node.SetAttribute('r:id', rid); - break; - end - sheet_node := sheet_node.NextElement(); - end - //workbook.Print(); - - //设置docProps/app.xml - app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app')); - //app.Print(); - node := app.FirstChildElement('Properties').FirstChildElement('TitlesOfParts'); - vector := node.FirstChildElement('vt:vector'); - vector.SetAttribute('size', length(sheetNames_) + 1); - lpstr := vector.FirstChildElement('vt:lpstr'); - while ifObj(lpstr) do - begin - if LowerCase(lpstr.GetText()) = LowerCase(sourceSheet) then - begin - lpstr := vector.InsertAfterChild(lpstr, 'element', 'vt:lpstr'); - lpstr.SetValue(destSheet); - break; - end - lpstr := lpstr.NextElement(); - end - - //设置[Content_Types].xml - content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types')); - class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType')); + sheetId := addSheetN(fname); + rid := setWorkbookRels(); + insertWorkbookSheet(sourceSheet, destSheet, sheetId, rid, 'after'); + insertDocPropsApp(sourceSheet, destSheet, 'after'); + setContentTypes(fname); ind := sheetIndexMap_[sname]; for i:=sheetsCount_ downto ind+2 do @@ -345,66 +370,12 @@ Type xlsxWorkBook = Class sname := LowerCase(sourceSheet); if not ifint(sheetIndexMap_[ sname ]) then return 'sourceSheet does not exists'; - //添加文件xl/worksheets/sheetN.xml - sheetId := vselect maxof(['sheetId']) from sheetNames_ end; - sheetId := integer(sheetId) + 1; fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml'; - zipfile_.Add(fname, class(TSXml).XmlHeader() + class(TSXml).GetTemplate('sheet1')); - - //设置 workbook.xml.rels - rid := getWorkbookRelsRid(); - workbook_rels := GetXmlFileObj('xl/_rels/workbook.xml.rels'); - rels := workbook_rels.FirstChildElement('Relationships').InsertEndChild('element', 'Relationship'); - rels.SetAttribute('Target', getTarget( sheetsCount_ + 1)); - rels.SetAttribute('Type', class(TSXml).GetTemplate('RelationshipWorkSheet')); - rels.SetAttribute('Id', rid); - //workbook_rels.Print; - - //设置 xl/workbook.xml - workbook := GetXmlFileObj('xl/workbook.xml'); - node := workbook.FirstChildElement('workbook').FirstChildElement('sheets'); - sheet_node := node.FirstChildElement('sheet'); - prev_node := nil; - while ifObj(sheet_node) do - begin - if LowerCase(sheet_node.GetAttribute('name')) = LowerCase(sourceSheet) then - begin - if ifnil(prev_node) then sheet_node := node.InsertFirstChild('element', 'sheet'); - else sheet_node := node.InsertAfterChild(prev_node, 'element', 'sheet'); - sheet_node.SetAttribute('name', destSheet); - sheet_node.SetAttribute('sheetId', sheetId); - sheet_node.SetAttribute('r:id', rid); - break; - end - prev_node := sheet_node; - sheet_node := sheet_node.NextElement(); - end - //workbook.Print(); - - //设置docProps/app.xml - app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app')); - //app.Print(); - node := app.FirstChildElement('Properties').FirstChildElement('TitlesOfParts'); - vector := node.FirstChildElement('vt:vector'); - vector.SetAttribute('size', length(sheetNames_) + 1); - lpstr := vector.FirstChildElement('vt:lpstr'); - pstr := nil; - while ifObj(lpstr) do - begin - if LowerCase(lpstr.GetText()) = LowerCase(sourceSheet) then - begin - if ifnil(pstr) then lpstr := vector.InsertFirstChild('element', 'vt:lpstr'); - else lpstr := vector.InsertAfterChild(pstr, 'element', 'vt:lpstr'); - lpstr.SetValue(destSheet); - break; - end - pstr := lpstr; - lpstr := lpstr.NextElement(); - end - - //设置[Content_Types].xml - content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types')); - class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType')); + sheetId := addSheetN(fname); + rid := setWorkbookRels(); + insertWorkbookSheet(sourceSheet, destSheet, sheetId, rid, 'before'); + insertDocPropsApp(sourceSheet, destSheet, 'before'); + setContentTypes(fname); ind := sheetIndexMap_[sname]; for i:=sheetsCount_ downto ind+1 do diff --git a/更新日志.md b/更新日志.md index bd6c946..77dd181 100644 --- a/更新日志.md +++ b/更新日志.md @@ -1,5 +1,14 @@ # 更新日志 +## 2023-2-5 + +### V1.6.0 + +#### excel + +1. 兼容Excel2016,通过`NewSheet/InsertSheet`创建工作表不再提示修复错误 +2. 修复带有表头的二维数组通过`InsertTable`写入数据只写入表头未写入数据问题 + ## 2023-1-31 ### V1.5.9