Compare commits

..
9 Commits
Author SHA1 Message Date
csh 15e2cbe661 整理word内容作为unit 2023-12-07 13:41:06 +08:00
csh 3643be6231 update 2023-08-29 15:05:06 +08:00
csh e2e68efc30 Merge branch 'master' into word 2023-08-29 15:00:42 +08:00
csh 2384ca42b5 Merge branch 'master' into word 2023-07-14 10:37:15 +08:00
csh 8f6bdd212b update two template 2023-06-13 13:27:59 +08:00
csh d08dea6bc9 update TSTag 2023-05-19 10:41:46 +08:00
csh 10ef45f1a0 add TSTag and wordtemplate 2023-05-17 17:25:21 +08:00
csh c536c4d531 excel gettable中文 2023-05-17 13:57:13 +08:00
csh 4dc02530ba init word_templat 2023-05-16 16:49:34 +08:00
21 changed files with 1493 additions and 2728 deletions
+23 -23
View File
@@ -1,28 +1,28 @@
path := ExtractFileDir(ExtractFileDir(PluginPath())); path := ExtractFileDir(ExtractFileDir(PluginPath()));
{$IFNDEF Win32} {$IFNDEF Win32}
path := path + '\\funcext\\TSOffice\\TSXlsxFile.tsf'; path := path + '\\funcext\\TSOffice\\TSExcelFile.tsf';
{$ELSE} {$ELSE}
path := path + '/funcext/TSOffice/TSXlsxFile.tsf'; path := path + '/funcext/TSOffice/TSExcelFile.tsf';
{$ENDIF} {$ENDIF}
funcs := LoadClassInfo(path); funcs := LoadClassInfo(path);
testing := 1; testing := 1;
file := new TSXlsxFile(); file := new TSExcelFile();
[err, errinfo] := file.NewFile(); [err, errinfo] := file.NewFile();
if err then if err then
return PrintError("NewFile", err, errinfo); return PrintError("NewFile", err, errinfo);
PrintSuccess("NewFile", testing++); PrintSuccess("NewFile", testing++);
file.SetSheetName('Sheet1', 'XlsxFile'); file.SetSheetName('Sheet1', 'ExcelFile');
PrintSuccess("SetSheetName", testing++); PrintSuccess("SetSheetName", testing++);
file.NewSheet("Functions"); file.NewSheet("Functions");
PrintSuccess("NewSheet", testing++); PrintSuccess("NewSheet", testing++);
file.SetDefaultSheet('TSXlsxFile'); file.SetDefaultSheet('ExcelFile');
richtext := TOfficeObj('TRichText'); richtext := TOfficeObj('TRichText');
txt1 := richtext.AddText('TSXlsxFile类 '); txt1 := richtext.AddText('TSExcelFile类 ');
txt1.Font.Size := 35; txt1.Font.Size := 35;
txt1.Font.Color := "FF0000"; txt1.Font.Color := "FF0000";
txt1.Font.Bold := 1; txt1.Font.Bold := 1;
@@ -34,14 +34,14 @@ txt2.Font.Bold := 1;
txt2.Font.Italic := 1; txt2.Font.Italic := 1;
txt2.Font.Color := "FFC0CB"; txt2.Font.Color := "FFC0CB";
file.SetCellRichText('XlsxFile', 'A1', richtext); file.SetCellRichText('ExcelFile', 'A1', richtext);
PrintSuccess("SetCellRichText", testing++); PrintSuccess("SetCellRichText", testing++);
[err, richText] := file.GetCellRichText('XlsxFile', 'A1'); [err, richText] := file.GetCellRichText('ExcelFile', 'A1');
if err then if err then
return PrintError("GetCellRichText", err, errinfo); return PrintError("GetCellRichText", err, errinfo);
PrintSuccess("GetCellRichText", testing++); PrintSuccess("GetCellRichText", testing++);
file.MergeCell('XlsxFile', 'A1', 'C1'); file.MergeCell('ExcelFile', 'A1', 'C1');
PrintSuccess("MergeCell", testing++); PrintSuccess("MergeCell", testing++);
@@ -65,15 +65,15 @@ style.Fill.Gradient.Stop2.Color := "E0EBF5";
styleId := file.NewStyle(style); styleId := file.NewStyle(style);
PrintSuccess("NewStyle", testing++); PrintSuccess("NewStyle", testing++);
file.SetCellStyle("XlsxFile", 'A1', 'C1', styleId); file.SetCellStyle("ExcelFile", 'A1', 'C1', styleId);
file.SetCellValue("XlsxFile", "A3", "索引"); file.SetCellValue("ExcelFile", "A3", "索引");
file.SetCellValue("XlsxFile", "B3", "函数名称"); file.SetCellValue("ExcelFile", "B3", "函数名称");
file.SetCellValue("XlsxFile", "C3", "功能"); file.SetCellValue("ExcelFile", "C3", "功能");
file.SetColWidth("XlsxFile", "A", "A", 6); file.SetColWidth("ExcelFile", "A", "A", 6);
file.SetColWidth("XlsxFile", "B", "B", 55); file.SetColWidth("ExcelFile", "B", "B", 55);
file.SetColWidth("XlsxFile", "C", "C", 100); file.SetColWidth("ExcelFile", "C", "C", 100);
file.SetCellStyle("XlsxFile", "A3", "C3", styleId); file.SetCellStyle("ExcelFile", "A3", "C3", styleId);
style2 := TOfficeObj("TStyle"); style2 := TOfficeObj("TStyle");
@@ -108,9 +108,9 @@ Begin
[err0, cell0] := file.CoordinatesToCellName(1, i+4); [err0, cell0] := file.CoordinatesToCellName(1, i+4);
[err1, cell1] := file.CoordinatesToCellName(2, i+4); [err1, cell1] := file.CoordinatesToCellName(2, i+4);
[err2, cell2] := file.CoordinatesToCellName(3, i+4); [err2, cell2] := file.CoordinatesToCellName(3, i+4);
file.SetCellValue("XlsxFile", cell0, i+1); file.SetCellValue("ExcelFile", cell0, i+1);
file.SetCellValue("XlsxFile", cell1, funcs[i]['funcname']); file.SetCellValue("ExcelFile", cell1, funcs[i]['funcname']);
file.SetCellValue("XlsxFile", cell2, funcs[i]['name']); file.SetCellValue("ExcelFile", cell2, funcs[i]['name']);
str := funcs[i]['name'] + "\nFunction " + funcs[i]['funcname'] + funcs[i]['comment']; str := funcs[i]['name'] + "\nFunction " + funcs[i]['funcname'] + funcs[i]['comment'];
arr := str2array(str, "\n"); arr := str2array(str, "\n");
@@ -130,15 +130,15 @@ Begin
hyperlink.LinkType := "location"; hyperlink.LinkType := "location";
hyperlink.LinkUrl := "Functions!" $ c1; hyperlink.LinkUrl := "Functions!" $ c1;
file.SetCellHyperLink("XlsxFile", cell1, hyperlink); file.SetCellHyperLink("ExcelFile", cell1, hyperlink);
file.SetCellStyle("XlsxFile", cell1, cell1, styleId4); file.SetCellStyle("ExcelFile", cell1, cell1, styleId4);
End End
file.SetColWidth('Functions', 'A', 'A', 120); file.SetColWidth('Functions', 'A', 'A', 120);
PrintSuccess('SetColWidth', testing++); PrintSuccess('SetColWidth', testing++);
saveName := utf8toansi("XlsxFile使用帮助.xlsx"); saveName := utf8toansi("ExcelFile使用帮助.xlsx");
[err, errinfo] := file.SaveAs('', saveName); [err, errinfo] := file.SaveAs('', saveName);
if err then if err then
return PrintError("SaveAs", err, errinfo); return PrintError("SaveAs", err, errinfo);
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -4
View File
@@ -12,19 +12,17 @@ TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
可选: 可选:
- `fmt_pubkrnl_plugin` 放入 tsl 安装根目录下 Plugin 文件夹,若需要执行Demo文件夹下的[XlsxHelp.tsl](./Demo/XlsxHelp.tsl)和[DocxHelp.tsl](./Demo/DocxHelp.tsl),需要部署改动态库 - `fmt_pubkrnl_plugin` 放入 tsl 安装根目录下 Plugin 文件夹,若需要执行Demo文件夹下的[ExcelHelp.tsl](./Demo/ExcelHelp.tsl)和[WordHelp.tsl](./Demo/WordHelp.tsl),需要部署改动态库
### Linux ### Linux
#### Ubuntu-18.04
根据架构选择aarch64或x86版本将对应文件夹内容进行部署 根据架构选择aarch64或x86版本将对应文件夹内容进行部署
- `liboffice_plugin` 放入 tsl 安装根目录下 Plugin 文件夹 - `liboffice_plugin` 放入 tsl 安装根目录下 Plugin 文件夹
## 帮助文档 ## 帮助文档
- [Excel 帮助文档](./XlsxFile使用帮助.xlsx) - [Excel 帮助文档](./ExcelFile使用帮助.xlsx)
- [Word 帮助文档](./DocxFile使用帮助.docx) - [Word 帮助文档](./DocxFile使用帮助.docx)
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large Load Diff
+8 -45
View File
@@ -1,4 +1,4 @@
// Version 1.5.2 // Version 1.4.4
Type TSDocxFile = Class Type TSDocxFile = Class
///Version: V1.0 2022-09-20 ///Version: V1.0 2022-09-20
@@ -124,13 +124,6 @@ Type TSDocxFile = Class
return document_.Body().Paragraphs(); return document_.Body().Paragraphs();
End; End;
///word文档最后一个段落
///返回:TParagraph对象
Function LastParagraph();
Begin
return document_.Body().LastParagraph();
End;
///添加新段落 ///添加新段落
///paragraph: TParagraph对象 ///paragraph: TParagraph对象
///posOpt: 段落位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加段落 ///posOpt: 段落位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加段落
@@ -237,12 +230,10 @@ Type TSDocxFile = Class
///插入数据表 ///插入数据表
///tbl: TTable对象 ///tbl: TTable对象
///posOpt: 段落位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加表格 ///posOpt: 段落位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加表格
///customCell: 二维数组,自定义指定单元格的样式
/// 如:一行一列arr[0][0] := array(twtcPr, twpPr, twrPr);其中twtcPr是twtcPr对象,twpPr是twpPr对象,twrPr是twrPr对象
///返回: TTable对象 ///返回: TTable对象
Function InsertTable(tbl, posOpt, customCell); Function InsertTable(tbl, posOpt);
Begin Begin
return document_.Body().InsertTable(tbl, getPosNode(posOpt), customCell); return document_.Body().InsertTable(tbl, getPosNode(posOpt));
End; End;
///返回CoreProperties对象 ///返回CoreProperties对象
@@ -381,25 +372,6 @@ Type TSDocxFile = Class
return nil; return nil;
End; End;
///复制Word内容
///alias: string,文件目录别名
///fileName: string,文件名
///posOpt: 段落位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加图片
///返回: [err, TDocxCopy对象]
///TDocxCopy.GetCopiedTable() 返回复制的对象表格数组
///TDocxCopy.GetCopiedParagraph() 返回复制对象的段落数组
///TDocxCopy.GetCopiedDrawing() 返回复制对象的图表数组
Function InsertFile(alias, fileName, posOpt);overload;
Begin
docxObj := new TSDocxFile();
[err, msg] := docxObj.OpenFile(alias, fileName);
if err then return array(err, msg);
copy_obj := new TDocxCopy(self, docxObj);
copy_obj.Init();
copy_obj.Copy(posOpt);
return array(0, copy_obj);
End;
///复制Word内容 ///复制Word内容
///docxObj: TSDocxFile对象 ///docxObj: TSDocxFile对象
///posOpt: 段落位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加图片 ///posOpt: 段落位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加图片
@@ -407,8 +379,11 @@ Type TSDocxFile = Class
///TDocxCopy.GetCopiedTable() 返回复制的对象表格数组 ///TDocxCopy.GetCopiedTable() 返回复制的对象表格数组
///TDocxCopy.GetCopiedParagraph() 返回复制对象的段落数组 ///TDocxCopy.GetCopiedParagraph() 返回复制对象的段落数组
///TDocxCopy.GetCopiedDrawing() 返回复制对象的图表数组 ///TDocxCopy.GetCopiedDrawing() 返回复制对象的图表数组
Function InsertFile(docxObj, posOpt);overload; Function InsertFile(alias, fileName, posOpt);
Begin Begin
docxObj := new TSDocxFile();
[err, msg] := docxObj.OpenFile(alias, fileName);
if err then return array(err, msg);
copy_obj := new TDocxCopy(self, docxObj); copy_obj := new TDocxCopy(self, docxObj);
copy_obj.Init(); copy_obj.Init();
copy_obj.Copy(posOpt); copy_obj.Copy(posOpt);
@@ -535,7 +510,7 @@ Type TSDocxFile = Class
///返回:array((("Level":level,"Paragraph":"object","Text":title)); ///返回:array((("Level":level,"Paragraph":"object","Text":title));
Function GetHeadingList(UpperHeadingLevel, LowerHeadingLevel); Function GetHeadingList(UpperHeadingLevel, LowerHeadingLevel);
Begin Begin
return document_.Body().GetHeadingListImpl(self, nil, UpperHeadingLevel, LowerHeadingLevel, nil); return document_.Body().GetHeadingListImpl(self, nil, UpperHeadingLevel, LowerHeadingLevel, nil, true);
End; End;
//返回Document对象 //返回Document对象
@@ -560,17 +535,6 @@ Type TSDocxFile = Class
return numberingObj_; return numberingObj_;
End; End;
///返回:TFootnotes对象
Function FootNotesObject();
Begin
if not ifObj(footnotesObj_) then
begin
footnotesObj_ := new TOfficeObj('TFootnoteBody');
footnotesObj_.InitFootnotes(self.Zip());
end
return footnotesObj_;
End;
///执行word文档内嵌tsl代码(执行内嵌脚本的环境字符集为GBK) ///执行word文档内嵌tsl代码(执行内嵌脚本的环境字符集为GBK)
///返回:[err,tslFuncCount,errArr]: err 执行错误TSL代码段次数,tslFuncCount TSL代码段总数,errArr 执行TSL错误信息(array(('code':'代码', 'err':'错误信息')) ///返回:[err,tslFuncCount,errArr]: err 执行错误TSL代码段次数,tslFuncCount TSL代码段总数,errArr 执行TSL错误信息(array(('code':'代码', 'err':'错误信息'))
Function ExecInnerTSL(); Function ExecInnerTSL();
@@ -627,7 +591,6 @@ private
zipfile_; //压缩文件对象 zipfile_; //压缩文件对象
document_; //Document对象 document_; //Document对象
styleObj_; styleObj_;
footnotesObj_;
numberingObj_; numberingObj_;
DocPrId_; DocPrId_;
End; End;
+2 -2
View File
@@ -1,4 +1,4 @@
// Version 1.5.0 // Version 1.4.4
Type TSExcelFile = Class Type TSExcelFile = Class
///Version: V1.0 2022-08-08 ///Version: V1.0 2022-08-08
@@ -915,7 +915,7 @@ Type TSExcelFile = Class
///复制Sheet ///复制Sheet
///sourceSheet: 源工作表 ///sourceSheet: 源工作表
///destSheet: 目的工作表,如果destSheet存在,则覆盖destSheet,否则末尾新增destSheet ///destSheet: 目的工作表
Function CopySheet(sourceSheet, destSheet); Function CopySheet(sourceSheet, destSheet);
Begin Begin
return workbook_.CopySheet(class(TSXml).CurCodePageToUtf8(sourceSheet), class(TSXml).CurCodePageToUtf8(destSheet)); return workbook_.CopySheet(class(TSXml).CurCodePageToUtf8(sourceSheet), class(TSXml).CurCodePageToUtf8(destSheet));
+25 -19
View File
@@ -18,31 +18,25 @@ public
return RootObj; return RootObj;
End End
Function Update(position);overload; Function Update();
Begin Begin
if ifObj(RootObj) then Begin if ifObj(RootObj) then Begin
arr := Marshal(); arr := Marshal();
if length(arr['attributes']) or length(arr['children']) then Begin if length(arr['attributes']) or length(arr['children']) then Begin
curNode := class(TSXml).GetNode(RootObj, NodeUri, position); curNode := class(TSXml).GetNode(RootObj, NodeUri);
if ifObj(curNode) then if ifObj(curNode) then
class(TSXml).UpdateNode(curNode, arr['attributes'], arr['children']); class(TSXml).UpdateNode(curNode, arr['attributes'], arr['children']);
End; End;
End; End;
End; End;
Function Update();overload; Function HandleAttrs(); virtual;
Begin Begin
self.Update("end"); End
End;
Function Delete(); Function HandleChildren(); virtual;
Begin Begin
if ifObj(RootObj) then End
begin
curNode := class(TSXml).GetNode(RootObj, NodeUri);
if ifObj(curNode) then curNode.DeleteChildren();
end
End;
Function GetAttrs(); virtual; Function GetAttrs(); virtual;
Begin Begin
@@ -77,16 +71,27 @@ public
children_ := nil; children_ := nil;
GetChildrenEx(); //优化为变量,减少数据COPY2022-12-10 GetChildrenEx(); //优化为变量,减少数据COPY2022-12-10
child_arr := array(); child_arr := array();
name_map := array();
len := 0; len := 0;
for i:=0 to length(children_)-1 do for i:=0 to length(children_)-1 do
begin begin
node_type := children_[i]['nodeType']; node_type := children_[i]['nodeType'];
obj := children_[i]['obj']; obj := children_[i]['obj'];
if ifnil(obj) then continue; if ifnil(obj) then continue;
if not ifObj(obj) and not ifnil(name_map[children_[i]['name']]) and children_[i]['attrEx'] <> '' then //find := select thisrowindex as "rowindex_", * from child_arr where ['name'] = children_[i]['name'] end; //优化为循环,性能提高15-20%2022-12-20
find := array();
for j:=length(child_arr)-1 downto 0 do Begin //支持列表模式(如多节点:<w:t xml:space=""></w:t>),查找最近的节点
if child_arr[j]['name'] = children_[i]['name'] then Begin
find[0] := child_arr[j];
find[0]['rowindex_'] := j;
break;
End;
End;
if not ifnil(obj) and not ifObj(obj) and istable(find) and ifstring(children_[i]['attrEx']) and children_[i]['attrEx'] <> '' then
begin begin
child_arr[name_map[children_[i]['name']]]['attributes'] union=array(children_[i]['attrEx'] : obj); if not ifarray(find[0]['attributes']) then find[0]['attributes'] := array();
key := children_[i]['attrEx'];
find[0]['attributes'] union= array(key : obj);
child_arr[find[0]['rowindex_']]['attributes'] := find[0]['attributes'];
continue; continue;
end end
@@ -113,7 +118,7 @@ public
key := children_[i]['attrName'] ? children_[i]['attrName'] : children_[i]['attrEx'] ? children_[i]['attrEx'] : 'val'; key := children_[i]['attrName'] ? children_[i]['attrName'] : children_[i]['attrEx'] ? children_[i]['attrEx'] : 'val';
arr['attributes'] := array(key : obj); arr['attributes'] := array(key : obj);
end end
name_map[children_[i]['name']] := len;
child_arr[len++] := arr; child_arr[len++] := arr;
end end
@@ -149,7 +154,7 @@ public
return 1; return 1;
End End
Function Value(name, nottransferable); Function Value(name);
Begin Begin
if not ifObj(RootObj) then return nil; if not ifObj(RootObj) then return nil;
if NodeUri <> '' then if NodeUri <> '' then
@@ -164,7 +169,7 @@ public
if istable(r) then if istable(r) then
begin begin
value := node.GetAttribute(r[1]); value := node.GetAttribute(r[1]);
return nottransferable ? value : trystrtofloat(value, r) ? r : value; return trystrtofloat(value, r) ? r : value;
end end
children := GetChildren(); children := GetChildren();
@@ -181,7 +186,7 @@ public
key := r['attrName'] ? r['attrName'] : r['attrEx'] ? r['attrEx'] : 'val'; key := r['attrName'] ? r['attrName'] : r['attrEx'] ? r['attrEx'] : 'val';
value := node.GetAttribute(key); value := node.GetAttribute(key);
if r['nodeType'] = 'empty' and value = '' then return true; if r['nodeType'] = 'empty' and value = '' then return true;
return nottransferable ? value : trystrtofloat(value, r) ? r : value; return trystrtofloat(value, r) ? r : value;
End; End;
return nil; return nil;
End; End;
@@ -264,6 +269,7 @@ public
NodeName; NodeName;
ExtAttr; ExtAttr;
ExtNodes; ExtNodes;
//Parent;
ReplaceArr; ReplaceArr;
RootObj; // xml node RootObj; // xml node
NodeUri:string; NodeUri:string;
+3 -5
View File
@@ -71,14 +71,12 @@ Type TSImage = Class
Begin Begin
des1 := 0xff; des1 := 0xff;
des2 := 0xc0; des2 := 0xc0;
des3 := 0xc2;
flag := 1; flag := 1;
while flag do while flag do
begin begin
r1 := stringObj_.Read(byte1, 1); stringObj_.Read(byte1, 1);
r2 := stringObj_.Read(byte2, 1); stringObj_.Read(byte2, 1);
if r1 = 0 or r2 = 0 then break; if byte1 = des1 and byte2 = des2 then flag := 0;
if byte1 = des1 and (byte2 = des2 or byte2 = des3) then flag := 0;
end end
if flag then return array(0, 0); if flag then return array(0, 0);
stringObj_.Read(tmp, 3); stringObj_.Read(tmp, 3);
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
+12 -107
View File
@@ -9,7 +9,6 @@ Type TDocxCopy = class
copy_drawing_ := array(); copy_drawing_ := array();
style_copy_obj_ := new TDocxStyleCopy(oldObj.StyleObject(), newObj.StyleObject()); style_copy_obj_ := new TDocxStyleCopy(oldObj.StyleObject(), newObj.StyleObject());
number_copy_obj_ := new TDocxNumberCopy(oldObj, newObj); number_copy_obj_ := new TDocxNumberCopy(oldObj, newObj);
footnote_copy_obj_ := new TDocxFootnoteCopy(oldObj, newObj);
End; End;
Function Init(); Function Init();
@@ -22,7 +21,7 @@ Type TDocxCopy = class
Function Copy(posOpt); Function Copy(posOpt);
Begin Begin
// 复制所有的样式 // 复制所有的样式
style_copy_obj_.CopyStyle(number_copy_obj_); style_copy_obj_.CopyStyle();
parts := new_docx_obj_.Body().Parts(); parts := new_docx_obj_.Body().Parts();
pos := old_docx_obj_.GetPosNode(posOpt); pos := old_docx_obj_.GetPosNode(posOpt);
@@ -111,7 +110,6 @@ private
// 比较新文件的图片在旧文件中是否存在 // 比较新文件的图片在旧文件中是否存在
zip := old_docx_obj_.Zip(); zip := old_docx_obj_.Zip();
xml := zip.Get('word/_rels/document.xml.rels');
files := sselect ['FileName'] from zip.Files() where AnsiStartsText('word/media/image', ['FileName']) end; files := sselect ['FileName'] from zip.Files() where AnsiStartsText('word/media/image', ['FileName']) end;
for i:=0 to length(files)-1 do Begin for i:=0 to length(files)-1 do Begin
if zip.Diff(files[i], image_file) = 0 then Begin if zip.Diff(files[i], image_file) = 0 then Begin
@@ -119,6 +117,7 @@ private
[maxRid, imageFile, rid] := class(TSXml).FindRelationshipRid(xml, prefix); [maxRid, imageFile, rid] := class(TSXml).FindRelationshipRid(xml, prefix);
End; End;
End; End;
xml := zip.Get('word/_rels/document.xml.rels');
if rid = 0 then if rid = 0 then
begin begin
image_cnt := length(files) + 1; image_cnt := length(files) + 1;
@@ -132,9 +131,9 @@ private
zip.Add('word/' + image_path, image_file); zip.Add('word/' + image_path, image_file);
contentXml := zip.Get('[Content_Types].xml'); contentXml := zip.Get('[Content_Types].xml');
class(TSXml).AddDefaultContentType(contentXml, postfix, 'image/' $ postfix); class(TSXml).AddDefaultContentType(contentXml, postfix, 'image/' $ postfix);
end
end
node.SetAttribute('r:embed', 'rId' $ rid); node.SetAttribute('r:embed', 'rId' $ rid);
end
end
End; End;
Function SetChart(node); Function SetChart(node);
@@ -211,64 +210,21 @@ private
Function SetParagraphInfo(paragraph); Function SetParagraphInfo(paragraph);
Begin Begin
CopyStyle(paragraph.node_, 'w:pPr/w:pStyle'); style := class(TSXml).GetNode(paragraph.node_, 'w:pPr/w:pStyle');
CopyNumber(paragraph.node_, 'w:pPr/w:numPr/w:numId');
SetRunsInfo(paragraph.node_);
DeleteComment(paragraph); // 删除批注
End;
Function SetRunsInfo(node);
Begin
run := node.FirstChildElement('w:r');
while ifObj(run) do
begin
CopyFootnote(run);
CopyStyle(run, 'w:rPr/w:rStyle');
run := run.NextElement();
end
End;
Function CopyStyle(node, path);
Begin
style := class(TSXml).GetNode(node, path);
if ifObj(style) then if ifObj(style) then
begin begin
styleid := style.GetAttribute('w:val'); styleid := style.GetAttribute('w:val');
new_id := style_copy_obj_.GetStyleNewId(styleid); new_id := style_copy_obj_.GetStyleNewId(styleid);
if new_id then style.SetAttribute('w:val', new_id); if new_id then style.SetAttribute('w:val', new_id);
end end
End; numpr := class(TSXml).GetNode(paragraph.node_, 'w:pPr/w:numPr/w:numId');
Function CopyNumber(node, path);
Begin
numpr := class(TSXml).GetNode(node, path);
if ifObj(numpr) then if ifObj(numpr) then
begin begin
id := numpr.GetAttribute('w:val'); id := numpr.GetAttribute('w:val');
numberid := number_copy_obj_.CopyNumbering(id); numberid := number_copy_obj_.CopyNumbering(id);
numpr.SetAttribute('w:val', numberid); numpr.SetAttribute('w:val', id);
end
End;
Function CopyFootnote(node);
Begin
footnote := node.FirstChildElement('w:footnoteReference');
if not ifObj(footnote) then return;
id := footnote.GetAttribute('w:id');
if id then
begin
obj := footnote_copy_obj_.CopyFootnote(id);
footnote.SetAttribute('w:id', obj.Id);
parts := obj.Parts();
for i:=0 to length(parts)-1 do
begin
case GetPartType(parts[i]) of
0: SetParagraphInfo(parts[i]);
1: SetDrawingInfo(parts[i]);
2: SetTableInfo(parts[i]);
end;
end
end end
DeleteComment(paragraph); // 删除批注
End; End;
Function SetTableInfo(table); Function SetTableInfo(table);
@@ -339,7 +295,6 @@ private
new_docx_obj_; new_docx_obj_;
style_copy_obj_; style_copy_obj_;
number_copy_obj_; number_copy_obj_;
footnote_copy_obj_;
copy_table_; copy_table_;
copy_paragraph_; copy_paragraph_;
@@ -371,12 +326,11 @@ Type TDocxStyleCopy = class
end end
End; End;
Function CopyStyle(numberobj); Function CopyStyle();
Begin Begin
for id, obj in id_map_ do for id, obj in id_map_ do
begin begin
SetBasedOn(obj); SetBasedOn(obj);
SetNumId(obj, numberobj);
SetLink(obj); SetLink(obj);
old_style_obj_.CopyStyle(obj); old_style_obj_.CopyStyle(obj);
end; end;
@@ -428,23 +382,11 @@ private
end end
End; End;
Function SetNumId(obj, numberobj);
Begin
if not ifObj(numberobj) then return;
numPr := class(TSXml).GetNode(obj.node_, 'w:pPr/w:numPr/w:numId');
if ifObj(numPr) then
begin
id := numpr.GetAttribute('w:val');
numberid := numberobj.CopyNumbering(id);
numpr.SetAttribute('w:val', numberid);
end
End;
Function GetNewName(name); Function GetNewName(name);
Begin Begin
new_name := name; new_name := name;
count := 0; count := 0;
while ifObj(old_style_obj_.GetStyle(class(TSXml).Utf8ToCurCodePage(new_name))) or style_name_map2_[new_name] do while ifObj(old_style_obj_.GetStyle(new_name)) or style_name_map2_[new_name] do
new_name := new_name $ count++; new_name := new_name $ count++;
return new_name; return new_name;
End; End;
@@ -495,9 +437,9 @@ Type TDocxNumberCopy = class
begin begin
number_obj := old_number_obj_.CopyNumber(obj); number_obj := old_number_obj_.CopyNumber(obj);
id_map_[number] := number_obj; id_map_[number] := number_obj;
return number_obj;
end end
return id_map_[number]; end;
end
End; End;
private private
@@ -506,40 +448,3 @@ private
id_map_; // [id: styleobj] id_map_; // [id: styleobj]
End; End;
Type TDocxFootnoteCopy = class
Function Create(oldObj, newObj);
Begin
footnotexml := newObj.Zip().Get('word/footnotes.xml');
if ifObj(footnotexml) then
begin
old_footnote_obj_ := oldObj.FootNotesObject();
new_footnote_obj_ := newObj.FootNotesObject();
end
else begin
old_footnote_obj_ := nil;
new_footnote_obj_ := nil;
end
id_map_ := array();
End;
Function CopyFootnote(id);
Begin
if ifObj(old_footnote_obj_) and ifObj(new_footnote_obj_) then
begin
if (obj := new_footnote_obj_.GetFootnote(id)) and not id_map_[id] then
begin
footnote_obj := old_footnote_obj_.CopyFootnote(obj);
id_map_[id] := footnote_obj;
end
return id_map_[id];
end
End;
private
old_footnote_obj_;
new_footnote_obj_;
id_map_; // [id: footnote]
End;
@@ -0,0 +1,297 @@
Unit TSWordTemplateMethods;
Interface
Function ExcelChartCopyPic(excelFileName, excelSheetName, chartName, width, height);
Function WordAddOleObjectFromFile(fileName, width, height);
Function WordBr();
Function WordCopyFromExcel(excelFileName, excelSheetName, startRow, startCol, endRow, endCol);
Function WordGetCurrentDocument();
Function WordGetCurrentRange();
Function WordGetFont(prop, value);
Function WordGetLastRange();
Function WordGetLastShape();
Function WordGetLastTable();
Function WordGetLastTableCellProp(row, col, name, value);
Function WordGetLastTableProp(name, value);
Function WordLastTableMerge(row1, col1, row2, col2);
Function WordSetCurrentRange(range);
Function WordSetFont(prop, value);
Function WordSetLastTableCellProp(row, col, name, value);
Function WordSetLastTableProp(name, value);
Function WordSetRangeProp(name, value);
Function WordTemplate(data, template, fileName);
Function WordWrite();
Function WordWritePicFromFile(fileName);
Function WordWriteTable(table, writeIntIndex, writeIntTitle, incIntIndex);
Implementation
Function ExcelChartCopyPic(excelFileName, excelSheetName, chartName, width, height);
Begin
docx := TOfficeApi().GetDocument();
chart := docx.CopyExcelChart(excelFileName, excelSheetName, chartName, width, height, TOfficeApi().GetCurrentPosition());
return ifObj(chart);
End;
Function WordBr();
Begin
TOfficeApi().GetDocument().AddLineBreak(TOfficeApi().Get('CurrentPosition'));
End;
Function WordCopyFromExcel(excelFileName, excelSheetName, startRow, startCol, endRow, endCol);
Begin
excel := new TSXlsFile();
[err, msg] := excel.OpenFile('', excelFileName);
if err then return false;
total_row := excel.TotalRows(excelSheetName);
total_col := excel.TotalCols(excelSheetName);
if not total_row or not total_col then return false;
if ifnil(startRow) then
startRow := 1;
if ifnil(startCol) then
startCol := 1;
if ifnil(endRow) then
endRow := total_row;
if ifnil(endCol) then
endCol := total_col;
data := excel.GetTable(excelSheetName,
CoordinatesToCellName(startCol, startRow),
CoordinatesToCellName(endCol, endRow),
false,
false,
false);
if length(data) = 0 then return false;
//println('data={}',data);
docx := TOfficeApi().GetDocument();
tbl := docx.CreateTable(data, false, false);
tbl.Format.Borders.Top.Val := 'dashed';
tbl.Format.Borders.Left.Val := 'dashed';
tbl.Format.Borders.Bottom.Val := 'dashed';
tbl.Format.Borders.Right.Val := 'dashed';
tbl.Format.Borders.InsideH.Val := 'dashed';
tbl.Format.Borders.InsideV.Val := 'dashed';
tbl := docx.InsertTable(tbl, TOfficeApi().GetCurrentPosition());
End;
Function WordGetCurrentDocument();
Begin
return TOfficeApi().GetDocument();
End;
Function WordGetCurrentRange();
Begin
return TOfficeApi().GetCurrentPosition();
End;
Function WordGetFont(prop, value);
Begin
crun := TOfficeApi().GetCurrentRun();
node := crun.Node().FirstChildElement('w:rPr');
rPr := TOfficeObj('TwrPr');
rPr.InitRootNode(node);
value := rPr.Value(prop);
if not ifnil(value) then return true;
return false;
End;
Function WordGetLastShape();
Begin
node := TOfficeApi().Get('CurrentShape');
if not ifObj(node) then return nil;
uri := 'w:r/w:drawing/wp:inline/a:graphic/a:graphicData/c:chart';
cNode := class(TSXml).GetNode(node, uri);
if ifObj(cNode) then Begin
chart := TOfficeObj('TChart');
chart.Init(TOfficeApi().GetDocument(), node, cNode);
return chart;
End;
pic := TOfficeObj('TPicture');
pic.Init(node);
return pic;
End;
Function WordGetLastRange();
Begin
return TOfficeApi().GetCurrentPosition();
End;
Function WordGetLastTable();
Begin
return TOfficeApi().Get('CurrentTable');
End;
Function WordGetLastTableCellProp(row, col, name, value);
Begin
table_node := TOfficeApi().Get('CurrentTable');
if ifnil(table_node) then return false;
table := TOfficeObj("TTable");
table.Init(table_node);
table_cell := table.Cell(row, col);
ctr := _wordCompTable();
name_ := ctr[lowercase(name)];
if ifnil(name_) then name_ := name;
str := 'return table_cell.Format.' $ name_ $ '"' $ value $ '"';
value := eval(&str);
return true;
End;
Function WordGetLastTableProp(name, value);
Begin
table_node := TOfficeApi().Get('CurrentTable');
if ifnil(table_node) then return false;
table := TOfficeObj("TTable");
table.Init(table_node);
ctr := _wordCompTable();
name_ := ctr[lowercase(name)];
if ifnil(name_) then name_ := name;
str := 'return table.Format.' $ name_ $ '"' $ value $ '"';
value := eval(&str);
return true;
End;
Function WordLastTableMerge(row1, col1, row2, col2);
Begin
table_node := TOfficeApi().Get('CurrentTable');
if ifnil(table_node) then return false;
table := TOfficeObj("TTable");
table.Init(table_node);
[err1, beg_cell] := CoordinatesToCellName(col1, row1);
[err2, end_cell] := CoordinatesToCellName(col2, row2);
if err1 or err2 then return false;
table.Merge(beg_cell, end_cell, false);
return true;
End;
Function WordSetCurrentRange(range);
Begin
TOfficeApi().Set('CurrentPosition', range);
End;
Function WordSetFont(prop, value);
Begin
run := TOfficeApi().GetCurrentRun();
str := 'run.font.' $ prop $ ' := ' $ '"' $ value $ '"';
eval(&str);
run.Apply();
return true;
End;
Function WordSetLastTableCellProp(row, col, name, value);
Begin
table := TOfficeApi().Get('CurrentTable');
if ifnil(table) then return false;
table_cell := table.Cell(row, col);
ctr := _wordCompTable();
name_ := ctr[lowercase(name)];
if ifnil(name_) then name_ := name;
str := 'table_cell.Format.' $ name_ $ ' := ';
if ifstring(value) then
str += '"' $ value $ '"';
else
str := str $ value;
eval(&str);
return true;
End;
Function WordSetLastTableProp(name, value);
Begin
table := TOfficeApi().Get('CurrentTable');
if ifnil(table) then return false;
ctr := _wordCompTable();
name_ := ctr[lowercase(name)];
if ifnil(name_) then name_ := name;
str := 'table.Format.' $ name_ $ ' := ';
if ifstring(value) then
str += '"' $ value $ '"';
else
str := str $ value;
eval(&str);
TOfficeApi().Set('CurrentTable', table);
return true;
End;
Function WordSetRangeProp(name, value);
Begin
cur := TOfficeApi().GetCurrentPosition();
if ifnil(cur) then return nil;
End;
Function WordTemplate(data, template, fileName);
Begin
setsysparam('data', data);
docx := new TSDocxFile();
[err, msg] := docx.OpenFile('', template);
if err then return false;
docx.ExecInnerTSL();
if ifstring(fileName) then
begin
[err, msg] := docx.SaveAs('', fileName);
if err then return false;
end
return true;
End;
Function WordWrite();
Begin
docx := TOfficeApi().GetDocument();
curParagraph := TOfficeApi().GetCurrentParagraph();
curRun := TOfficeApi().GetCurrentRun();
for i:=1 to PARAMCOUNT do Begin
argv := params[i];
if ifstring( argv ) then
curRun.AddText( argv );
else if ifnumber(argv) then
curRun.AddText('' $ argv);
else if ifarray(argv) then Begin
tbl := docx.CreateTable(argv, false, false);
tbl := docx.InsertTable(tbl, TOfficeApi().GetCurrentPosition());
End
End
End;
Function WordWritePicFromFile(fileName);
Begin
file_size := fileSize('', fileName);
flag := readfile(rwbinary(), '', fileName, 0, file_size, data);
if not flag then return false;
picture := TOfficeObj('TPicture');
picture.Image := data;
docx := TOfficeApi().GetDocument();
docx.AddPicture(picture, TOfficeApi().GetCurrentPosition());
return true;
End;
Function WordWriteTable(table, writeIntIndex, writeIntTitle, incIntIndex);
Begin
docx := TOfficeApi().GetDocument();
tbl := docx.CreateTable(table, true, writeIntIndex);
table := docx.InsertTable(tbl, TOfficeApi().GetCurrentPosition());
return true;
End;
Function _wordCompTable();
Begin
return array(
'alignment': 'Alignment',
'shadingcolor': 'Shading.Color',
'style': 'StyleID',
'verticalalignment': 'Valign',
'width': 'Width',
);
End;
// TODO:尚未支持
Function WordAddOleObjectFromFile(fileName, width, height);
Begin
End;
Function WordCopyPicFormatExcel(excelFileName, excelSheetName, startRow, startCol, endRow, endCol, picType);
Begin
End;
Function WordGetRangeProp(name, value);
Begin
End;
Function WordLastTableSplit(row, col, rCnt, cCnt);
Begin
End;
End.
+5 -25
View File
@@ -142,7 +142,7 @@ Type TTableContent = class
Begin Begin
///获取标题列表 array((("Level":level,"Paragraph":"object","Text":title,"numId":,"ilvl":,"numArr":)); ///获取标题列表 array((("Level":level,"Paragraph":"object","Text":title,"numId":,"ilvl":,"numArr":));
numMap := array(); numMap := array();
r := docx_.Document().Body().GetHeadingListImpl(docx_, nil, UpperHeadingLevel, LowerHeadingLevel, numMap); r := docx_.Document().Body().GetHeadingListImpl(docx_, posOpt, UpperHeadingLevel, LowerHeadingLevel, numMap, true);
for i:=0 to length(r)-1 do Begin for i:=0 to length(r)-1 do Begin
p := _AddItem(UpperHeadingLevel, LowerHeadingLevel, r[i]['Level'], i = 0 ? true: false); p := _AddItem(UpperHeadingLevel, LowerHeadingLevel, r[i]['Level'], i = 0 ? true: false);
//fldCharType //fldCharType
@@ -160,9 +160,9 @@ Type TTableContent = class
if ifObj(style) then if ifObj(style) then
numStr := style.GetText(r[i]['ilvl'], r[i]['numArr']); numStr := style.GetText(r[i]['ilvl'], r[i]['numArr']);
End End
run_t := class(TSXml).CurCodePageToUtf8(r[i]['Text']); if numStr <> '' then run_t := numStr + ' ' + r[i]['Text'];
if numStr <> '' then run_t := numStr + ' ' + run_t; else run_t := r[i]['Text'];
r1.SetText(run_t, 1); r1.SetText(run_t);
r2 := h.AddRun(); r2 := h.AddRun();
r2.rPr.noProof := true; r2.rPr.noProof := true;
@@ -203,6 +203,7 @@ Type TTableContent = class
r8.fldCharType := 'end'; r8.fldCharType := 'end';
_AddStdContent(p); _AddStdContent(p);
End; End;
p2 := TOfficeObj('TParagraph'); p2 := TOfficeObj('TParagraph');
@@ -220,26 +221,6 @@ Type TTableContent = class
Begin Begin
End; End;
Function Paragraphs();
Begin
node := class(TSXml).GetNode(docx_.Document().Body().Node(), 'w:sdt/w:sdtContent');
r := array();
if ifObj(node) then
begin
twbody := TOfficeObj('TwBody');
twbody.Create(nil, 'w:sdtContent');
twbody.InitRootNode(node);
twbody.InitNode(node);
parts := twbody.Paragraphs();
for i:=0 to length(parts)-1 do
begin
r[i] := TOfficeObj('TParagraph');
r[i].Init(parts[i].node_);
end
end
return r;
End;
Function Marshal(); Function Marshal();
Begin Begin
return impl_.Marshal(); return impl_.Marshal();
@@ -318,4 +299,3 @@ Type TTableContent = class
node_; node_;
impl_; impl_;
End; End;
+1 -2
View File
@@ -10,7 +10,6 @@ Type docxDocument = Class
bodyNode_ := root_.FirstChildElement('w:body'); bodyNode_ := root_.FirstChildElement('w:body');
body_ := TOfficeObj('TwBody'); body_ := TOfficeObj('TwBody');
body_.InitNode(bodyNode_); body_.InitNode(bodyNode_);
body_.InitRootNode(bodyNode_);
body_.zipfile_ := z; body_.zipfile_ := z;
body_.document_ := self; body_.document_ := self;
bookmarkid_ := -1; bookmarkid_ := -1;
@@ -30,7 +29,7 @@ Type docxDocument = Class
markStart := p.FirstChildElement('w:bookmarkStart'); markStart := p.FirstChildElement('w:bookmarkStart');
if ifObj(markStart) then Begin if ifObj(markStart) then Begin
id := markStart.GetAttribute('w:id'); id := markStart.GetAttribute('w:id');
if ifstring(id) and id <> '' then Begin if ifstring(id) then Begin
iVal := strtoint(id); iVal := strtoint(id);
if bookmarkid_ <= iVal then if bookmarkid_ <= iVal then
bookmarkid_ := iVal + 1; bookmarkid_ := iVal + 1;
+60 -73
View File
@@ -166,70 +166,63 @@ Type xlsxWorkBook = Class
Begin Begin
lname := LowerCase(sheet); lname := LowerCase(sheet);
if ifint(sheetIndexMap_[ lname ]) then return 'The sheet already exists.'; if ifint(sheetIndexMap_[ lname ]) then return 'The sheet already exists.';
rid := getWorkbookRelsRid();
fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml';
sheetId := addSheetN(fname);
rid := setWorkbookRels();
setWorkbookSheet(sheet, sheetId, rid);
setDocPropsApp(sheet);
setContentTypes(fname);
sheetNames_[sheetsCount_]['name'] := sheet;
sheetNames_[sheetsCount_]['sheetId'] := sheetId;
sheetNames_[sheetsCount_]['rid'] := rid;
sheetNames_[sheetsCount_]['file'] := fname;
sheetIndexMap_[ lname ] := sheetsCount_;
sheetsCount_ ++;
SetDefaultSheet(sheet);
End;
Function addSheetN(fname);
Begin
//添加文件xl/worksheets/sheetN.xml //添加文件xl/worksheets/sheetN.xml
sheetId := vselect maxof(['sheetId']) from sheetNames_ end; sheetId := vselect maxof(['sheetId']) from sheetNames_ end;
sheetId := integer(sheetId) + 1; sheetId := integer(sheetId) + 1;
fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml';
zipfile_.Add(fname, class(TSXml).XmlHeader() + class(TSXml).GetTemplate('sheet1')); zipfile_.Add(fname, class(TSXml).XmlHeader() + class(TSXml).GetTemplate('sheet1'));
return sheetId;
End;
Function setWorkbookRels();
Begin
rid := getWorkbookRelsRid();
//设置 workbook.xml.rels //设置 workbook.xml.rels
workbook_rels := GetXmlFileObj('xl/_rels/workbook.xml.rels'); workbook_rels := GetXmlFileObj('xl/_rels/workbook.xml.rels');
rels := workbook_rels.FirstChildElement('Relationships').InsertEndChild('element', 'Relationship'); rels := workbook_rels.FirstChildElement('Relationships').InsertEndChild('element', 'Relationship');
rels.SetAttribute('Target', getTarget( sheetsCount_ + 1)); rels.SetAttribute('Target', getTarget( sheetsCount_ + 1));
rels.SetAttribute('Type', class(TSXml).GetTemplate('RelationshipWorkSheet')); rels.SetAttribute('Type', class(TSXml).GetTemplate('RelationshipWorkSheet'));
rels.SetAttribute('Id', rid); rels.SetAttribute('Id', rid);
return rid; //workbook_rels.Print;
End;
Function setWorkbookSheet(sheetName, sheetId, rid);
Begin
//设置 xl/workbook.xml //设置 xl/workbook.xml
workbook := GetXmlFileObj('xl/workbook.xml'); workbook := GetXmlFileObj('xl/workbook.xml');
node := workbook.FirstChildElement('workbook').FirstChildElement('sheets').InsertEndChild('element','sheet'); node := workbook.FirstChildElement('workbook').FirstChildElement('sheets').InsertEndChild('element','sheet');
node.SetAttribute('name', sheetName); node.SetAttribute('name', sheet);
node.SetAttribute('sheetId', sheetId); node.SetAttribute('sheetId', sheetId);
node.SetAttribute('r:id', rid); node.SetAttribute('r:id', rid);
End; //workbook.Print();
Function setDocPropsApp(sheet);
Begin
//设置docProps/app.xml //设置docProps/app.xml
app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app')); app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app'));
vector := class(TSXml).GetNode(app, 'Properties/TitlesOfParts/vt:vector'); //app.Print();
node := app.FirstChildElement('Properties').FirstChildElement('TitlesOfParts');
if not ifObj(node) then Begin
node := app.FirstChildElement('Properties').InsertEndChild('element','TitlesOfParts');
End;
vector := node.FirstChildElement('vt:vector');
if not ifObj(vector) then Begin
vector := node.InsertEndChild('element', 'vt:vector');
vector.SetAttribute('baseType', 'lpstr');
vector.SetAttribute('size', length(sheetNames_) + 1);
for i:=0 to length(sheetNames_)-1 do Begin
vector.InsertEndChild('element', 'vt:lpstr', sheetNames_[i]['name']);
End;
End
else
vector.SetAttribute('size', length(sheetNames_) + 1); vector.SetAttribute('size', length(sheetNames_) + 1);
vector.InsertEndChild('element', 'vt:lpstr', sheet); vector.InsertEndChild('element', 'vt:lpstr', sheet);
End; //app.Print();
Function setContentTypes(fname);
Begin
//设置[Content_Types].xml //设置[Content_Types].xml
content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types')); content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types'));
class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType')); class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType'));
End;
sheetNames_[sheetsCount_]['name'] := sheet;
sheetNames_[sheetsCount_]['sheetId'] := sheetId;
sheetNames_[sheetsCount_]['rid'] := rid;
sheetNames_[sheetsCount_]['file'] := fname;
sheetIndexMap_[ LowerCase(sheet) ] := sheetsCount_;
sheetsCount_ ++;
SetDefaultSheet(sheet);
End;
Function NewSheet(sourceSheet, destSheet);overload; Function NewSheet(sourceSheet, destSheet);overload;
Begin Begin
@@ -519,19 +512,15 @@ Type xlsxWorkBook = Class
Function CopySheet(sourceSheet, destSheet); Function CopySheet(sourceSheet, destSheet);
Begin Begin
ind := sheetIndexMap_[ LowerCase(destSheet) ];
if ifint(ind) then return destSheet $ ' already exists.';
ind := sheetIndexMap_[ LowerCase(sourceSheet) ]; ind := sheetIndexMap_[ LowerCase(sourceSheet) ];
if not ifint(ind) then return sourceSheet $ ' does not exists.'; if not ifint(ind) then return sourceSheet $ ' does not exists.';
dest_ind := sheetIndexMap_[ LowerCase(destSheet) ];
//copy sheet //copy sheet
if ifint(dest_ind) then sheetId := vselect maxof(['sheetId']) from sheetNames_ end;
begin sheetId := integer(sheetId) + 1;
fname := sheetNames_[dest_ind]['file'];
zipfile_.Remove(fname);
end
else begin
fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml'; fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml';
end
sheet := GetSheetXmlFile(sourceSheet); sheet := GetSheetXmlFile(sourceSheet);
zipfile_.Add(fname, sheet.Data()); zipfile_.Add(fname, sheet.Data());
xml_file := GetXmlFileObj(fname); xml_file := GetXmlFileObj(fname);
@@ -560,14 +549,7 @@ Type xlsxWorkBook = Class
sheet_rels := GetSheetRelsFile(sourceSheet); sheet_rels := GetSheetRelsFile(sourceSheet);
if ifObj(sheet_rels) then if ifObj(sheet_rels) then
begin begin
if ifint(dest_ind) then
begin
rels_name := 'xl/worksheets/_rels/' + ExtractFileName(sheetNames_[dest_ind]['file']) + '.rels';
zipfile_.Remove(rels_name);
end
else begin
rels_name := 'xl/worksheets/_rels/' + 'sheet' + inttostr(sheetsCount_ + 1) + '.xml.rels'; rels_name := 'xl/worksheets/_rels/' + 'sheet' + inttostr(sheetsCount_ + 1) + '.xml.rels';
end
zipfile_.Add(rels_name, sheet_rels.Data()); zipfile_.Add(rels_name, sheet_rels.Data());
rels_file := GetXmlFileObj(rels_name); rels_file := GetXmlFileObj(rels_name);
relationship := rels_file.FirstChildElement('Relationships').FirstChildElement('Relationship'); relationship := rels_file.FirstChildElement('Relationships').FirstChildElement('Relationship');
@@ -594,8 +576,6 @@ Type xlsxWorkBook = Class
end end
end end
if ifint(dest_ind) then return;
//workbook.xml.rels //workbook.xml.rels
rid := getWorkbookRelsRid(); rid := getWorkbookRelsRid();
workbook_rels := GetXmlFileObj('xl/_rels/workbook.xml.rels'); workbook_rels := GetXmlFileObj('xl/_rels/workbook.xml.rels');
@@ -605,8 +585,6 @@ Type xlsxWorkBook = Class
rels.SetAttribute('Id', rid); rels.SetAttribute('Id', rid);
//xl/workbook.xml //xl/workbook.xml
sheetId := vselect maxof(['sheetId']) from sheetNames_ end;
sheetId := integer(sheetId) + 1;
workbook := GetXmlFileObj('xl/workbook.xml'); workbook := GetXmlFileObj('xl/workbook.xml');
node := workbook.FirstChildElement('workbook').FirstChildElement('sheets').InsertEndChild('element','sheet'); node := workbook.FirstChildElement('workbook').FirstChildElement('sheets').InsertEndChild('element','sheet');
node.SetAttribute('name', destSheet); node.SetAttribute('name', destSheet);
@@ -748,25 +726,23 @@ Type xlsxWorkBook = Class
Function SetSheetVisible(sheet, visible); Function SetSheetVisible(sheet, visible);
Begin Begin
workbook := GetXmlFileObj('xl/workbook.xml'); workbook := GetXmlFileObj('xl/workbook.xml');
node := class(TSXml).GetNode(workbook, 'workbook/sheets/sheet'); node := workbook.FirstChildElement('workbook').FirstChildElement('sheets').FirstChildElement('sheet');
if GetSheetsCount() = 1 then return "Only one sheet, can't set visible."; hidden := visible = 1 ? 0 : 1;
sheet := lowercase(sheet); default_sheet_name := GetDefaultSheet();
default_sheet_name := lowercase(GetDefaultSheet()); if default_sheet_name = sheet then
if default_sheet_name = sheet and not visible then
begin begin
ind := sheetIndexMap_[LowerCase(default_sheet_name)]; ind := sheetIndexMap_[LowerCase(default_sheet_name)];
default_name := ind = 0 ? sheetNames_[1]['name'] : sheetNames_[ind - 1]['name']; if ind = 0 then default_name := sheetNames_[ind + 1]['name'];
else default_name := sheetNames_[ind - 1]['name'];
SetDefaultSheet(default_name); SetDefaultSheet(default_name);
end end
if visible then SetDefaultSheet(sheet);
state := visible ? "nohidden" : "hidden";
while ifObj(node) do while ifObj(node) do
Begin Begin
name := lowercase(node.GetAttribute('name')); name := node.GetAttribute('name');
if name = sheet then if name = sheet then
Begin Begin
node.SetAttribute('state', state); if hidden then node.SetAttribute('state', 'hidden');
break; else node.DeleteAttribute('state');
End End
node := node.NextElement(); node := node.NextElement();
End End
@@ -777,12 +753,11 @@ Type xlsxWorkBook = Class
Begin Begin
sheet_file := GetSheetXmlFile(sheet); sheet_file := GetSheetXmlFile(sheet);
if not ifObj(sheet_file) then return 0; if not ifObj(sheet_file) then return 0;
sheet := lowercase(sheet);
workbook := GetXmlFileObj('xl/workbook.xml'); workbook := GetXmlFileObj('xl/workbook.xml');
node := class(TSXml).GetNode(workbook, 'workbook/sheets/sheet'); node := workbook.FirstChildElement('workbook').FirstChildElement('sheets').FirstChildElement('sheet');
while ifObj(node) do while ifObj(node) do
Begin Begin
name := lowercase(node.GetAttribute('name')); name := node.GetAttribute('name');
if name = sheet then if name = sheet then
Begin Begin
val := node.GetAttribute('state'); val := node.GetAttribute('state');
@@ -1129,17 +1104,29 @@ Type xlsxWorkBook = Class
node := sheet_node.InsertFirstChild('element', 'sheetView'); node := sheet_node.InsertFirstChild('element', 'sheetView');
node.SetAttribute('workbookViewId', 0); node.SetAttribute('workbookViewId', 0);
end end
if lowercase(name) = lowercase(sheet) then if name = sheet then
Begin Begin
node.SetAttribute('tabSelected', 1); node.SetAttribute('tabselected', 1);
workbook := GetXmlFileObj('xl/workbook.xml'); workbook := GetXmlFileObj('xl/workbook.xml');
view_node := class(TSXml).GetNode(workbook, 'workbook/bookViews/workbookView'); workbook_node := workbook.FirstChildElement('workbook');
book_view_node := workbook_node.FirstChildElement('bookViews');
if not ifObj(book_view_node) then
begin
prev_node := class(TSXml).GetWorkBookPrevNode(workbook_node, 'bookViews');
if not ifObj(prev_node) then book_view_node := workbook_node.InsertFirstChild('element', 'bookViews');
else book_view_node := workbook_node.InsertAfterChild(prev_node, 'element', 'bookViews');
end;
view_node := book_view_node.FirstChildElement('workbookView');
if not ifObj(view_node) then
begin
view_node := book_view_node.InsertFirstChild('element', 'workbookView');
end
view_node.SetAttribute('activeTab', ind); view_node.SetAttribute('activeTab', ind);
End End
else else
begin begin
node := root_node.FirstChildElement('sheetViews').FirstChildElement('sheetView'); node := root_node.FirstChildElement('sheetViews').FirstChildElement('sheetView');
node.SetAttribute('tabSelected', 0); node.SetAttribute('tabselected', 0);
end end
end end
End End
-87
View File
@@ -1,92 +1,5 @@
# 更新日志 # 更新日志
## 2023-12-1
### V1.5.2
#### excel
1. 修复公式中文转码问题
## 2023-11-15
### V1.5.1
1. 支持识别图片中含有`0xffc2`段的jpg格式的大小
## 2023-11-14
### V1.5.0
#### word
1. 新增对脚注的支持,方法`TSDocxFile.FootnotesObject().Add`
2. `TSDocxFile.InsertFile`支持脚注插入
### excel
1. 升级`TSXlsxFile.CopySheet`
## 2023-10-16
### V1.4.9
#### word
1. 新增`TSDocxFile.InsertFile`重载方法
2. 新增`Table.SetStyle`方法
## 2023-9-27
### V1.4.8
#### word
1. 支持`Inserttable`时候加入对单元格样式的设置
2. 新增`TSDocxFile.LastParagraph`方法
3. 新增`TParagraph.PrevParagraph`方法
4. 性能优化
## 2023-9-22
### V1.4.7
#### word
1. 修复项目符号属于样式时,生成目录无法识别出项目符号问题
## 2023-9-19
### V1.4.6
#### word
1. 修复表格存在合并单元格,生成目录报错问题
2. 修复单元格添加 run 对象,设置样式不生效问题
3. 修复插入 word 后,中文样式重复问题
### excel
🔔 重要升级:`TSExcelFile`更名为`TSXlsxFile`,建议更改,旧名字现阶段仍可使用
1. 整理`NewSheet``SetSheetVisible`代码
#### excel
1. 修复`NewSheet`excel 打开遇到提示错误问题
## 2023-8-30
### V1.4.5
#### word
1. 支持生成目录后返回目录对象的所有段落内容`目录对象.Paragraphs()`
#### excel
1. 修复`NewSheet`excel 打开遇到提示错误问题
## 2023-8-28 ## 2023-8-28
### V1.4.4 ### V1.4.4