v1.0.9
This commit is contained in:
parent
e2db550f99
commit
ce521a6a69
127
Demo/docx.tsl
127
Demo/docx.tsl
|
|
@ -1,127 +0,0 @@
|
||||||
docx := new TSDocxFile();
|
|
||||||
//_test_readParagraphs(docx);
|
|
||||||
_test_newfile(docx);
|
|
||||||
//_test_addtable(docx);
|
|
||||||
//_test_Properties(docx);
|
|
||||||
//_test_picture(docx);
|
|
||||||
|
|
||||||
|
|
||||||
Function _test_picture(docx);
|
|
||||||
Begin
|
|
||||||
[err, errmsg] := docx.NewFile();
|
|
||||||
if err then
|
|
||||||
return echo 'Open Fail:', errmsg, '\n';
|
|
||||||
|
|
||||||
picture := TOfficeObj('TPicture');
|
|
||||||
picture.Descr := 'Hans Tan\'s Picture test';
|
|
||||||
readfile(rwbinary(), '', 'F:\\temp\\VS2010Ultim\\Setup\\banner.bmp', 0, 1024*1024, data);
|
|
||||||
picture.Image := data;
|
|
||||||
p := docx.AddPicture(picture, -1);
|
|
||||||
|
|
||||||
v := docx.SaveAs('', 'f:\\temp\\p.docx');
|
|
||||||
println('Save={}', v);
|
|
||||||
End;
|
|
||||||
|
|
||||||
|
|
||||||
Function _test_Properties(docx);
|
|
||||||
Begin
|
|
||||||
f := 'F:\\temp\\test.docx';
|
|
||||||
[err, errmsg] := docx.OpenFile('', f);
|
|
||||||
if err then return
|
|
||||||
echo 'Open Fail:', errmsg, '\n';
|
|
||||||
|
|
||||||
core := docx.Properties();
|
|
||||||
core.Author := 'Hans Tan';
|
|
||||||
core.Modified := now();
|
|
||||||
|
|
||||||
docx.SaveAs('', 'f:\\temp\\core.docx');
|
|
||||||
End;
|
|
||||||
|
|
||||||
|
|
||||||
Function _test_addtable(docx);
|
|
||||||
Begin
|
|
||||||
[err, errmsg] := docx.NewFile();
|
|
||||||
if err then return
|
|
||||||
echo 'Open Fail:', errmsg, '\n';
|
|
||||||
|
|
||||||
data := array(("Name":"Small","Apple":2,"Orange":3,"Pear":3),
|
|
||||||
("Name":"Normal","Apple":5,"Orange":2,"Pear":4),
|
|
||||||
("Name":"Large","Apple":6,"Orange":7,"Pear":8));
|
|
||||||
tbl := docx.CreateTable(data, true, true);
|
|
||||||
//tbl.TblPr.Style := 1;
|
|
||||||
|
|
||||||
tbl := docx.InsertTable(tbl, -1);
|
|
||||||
|
|
||||||
v := docx.SaveAs('', 'f:\\temp\\t.docx');
|
|
||||||
println('Save={}', v);
|
|
||||||
End;
|
|
||||||
|
|
||||||
Function _test_newfile(docx);
|
|
||||||
Begin
|
|
||||||
[err, errmsg] := docx.NewFile();
|
|
||||||
if err then return
|
|
||||||
echo 'Open Fail:', errmsg, '\n';
|
|
||||||
|
|
||||||
paragraph := TOfficeObj('TParagraph');
|
|
||||||
paragraph.Run.Text := 'This is the 1 Line.';
|
|
||||||
p := docx.AddParagraph(paragraph, -1);
|
|
||||||
p := docx.AddLineBreak(p);
|
|
||||||
p := docx.AddLineBreak(p);
|
|
||||||
paragraph.Run.Text := 'This is the 2 Line.';
|
|
||||||
p := docx.AddParagraph(paragraph, -1);
|
|
||||||
p := docx.AddPageBreak(p);
|
|
||||||
|
|
||||||
paragraph.Run.Text := 'This is the 3 Line.';
|
|
||||||
p := docx.AddParagraph(paragraph, -1);
|
|
||||||
p := docx.AddColumnBreak(p);
|
|
||||||
paragraph.Run.Text := '';
|
|
||||||
p := docx.AddParagraph(paragraph, -1);
|
|
||||||
p.SetText('This is the 4 Line\nline5\nline6\nline7.');
|
|
||||||
|
|
||||||
v := docx.SaveAs('', 'f:\\temp\\new.docx');
|
|
||||||
println('Save={}', v);
|
|
||||||
|
|
||||||
End;
|
|
||||||
|
|
||||||
Function _test_readParagraphs(docx);
|
|
||||||
Begin
|
|
||||||
f := 'F:\\temp\\test.docx';
|
|
||||||
[err, errmsg] := docx.OpenFile('', f);
|
|
||||||
if err then return
|
|
||||||
echo 'Open Fail:', errmsg, '\n';
|
|
||||||
|
|
||||||
paragraph := TOfficeObj('TParagraph');
|
|
||||||
paragraph.Run.Text := 'New paragraph';
|
|
||||||
v := docx.AddParagraph(paragraph, 0);
|
|
||||||
paragraphs := docx.Paragraphs();
|
|
||||||
println("AddParagraph={}", v);
|
|
||||||
paragraphs[9].SetText('1、修改文字;
|
|
||||||
2、第2段;
|
|
||||||
3、第3段;
|
|
||||||
4、第4段。');
|
|
||||||
|
|
||||||
paragraphs := docx.Paragraphs();
|
|
||||||
for i:=0 to length(paragraphs)-1 do Begin
|
|
||||||
println('Name={}, Text={}', paragraphs[i].Name(), paragraphs[i].Text());
|
|
||||||
End;
|
|
||||||
|
|
||||||
tcnt := docx.TablesCount();
|
|
||||||
println('\n\nTableCount={}',tcnt);
|
|
||||||
for i := 0 to tcnt-1 do Begin
|
|
||||||
table := docx.GetTable(i);
|
|
||||||
for j := 0 to table.Rows()-1 do Begin
|
|
||||||
for k := 0 to table.Cols()-1 do Begin
|
|
||||||
cell := table.Cell(j, k);
|
|
||||||
if ifObj(cell) then Begin
|
|
||||||
println('row={}, col={}, text={}', j, k, cell.Text());
|
|
||||||
continue;
|
|
||||||
End;
|
|
||||||
println('row={}, col={}, Cell=nil', j, k);
|
|
||||||
End;
|
|
||||||
End;
|
|
||||||
End;
|
|
||||||
|
|
||||||
println('all text={}, textArray={}', docx.Text(), docx.TextArray());
|
|
||||||
|
|
||||||
docx.SaveAs('', 'f:\\temp\\p.docx');
|
|
||||||
End;
|
|
||||||
|
|
@ -59,6 +59,9 @@ _14_TDocxChart(docx);
|
||||||
///TOfficeApi
|
///TOfficeApi
|
||||||
_15_TOfficeApi(docx);
|
_15_TOfficeApi(docx);
|
||||||
|
|
||||||
|
///ExecInnerTSL
|
||||||
|
_16_Template(docx);
|
||||||
|
|
||||||
///附注
|
///附注
|
||||||
_Annotation(docx);
|
_Annotation(docx);
|
||||||
|
|
||||||
|
|
@ -68,7 +71,7 @@ _Faq(docx);
|
||||||
///目录
|
///目录
|
||||||
docx.AddTableContent(paragraphTitle, 1, 3);
|
docx.AddTableContent(paragraphTitle, 1, 3);
|
||||||
|
|
||||||
v := docx.SaveAs('', UTF8ToAnsi('DocxFile使用帮助.docx'));
|
v := docx.SaveAs('', TOfficeApi().CurCodePageToGBK('DocxFile使用帮助.docx'));
|
||||||
println('Test Over!\n Save {}: {},time={}秒', file, v, mtoc);
|
println('Test Over!\n Save {}: {},time={}秒', file, v, mtoc);
|
||||||
|
|
||||||
//info := GetProfilerInfo(true);
|
//info := GetProfilerInfo(true);
|
||||||
|
|
@ -801,12 +804,32 @@ Begin
|
||||||
_AddTitle(docx, 'TOfficeApi', 1);
|
_AddTitle(docx, 'TOfficeApi', 1);
|
||||||
|
|
||||||
_AddTitle(docx, 'TOfficeApi接口', 2);
|
_AddTitle(docx, 'TOfficeApi接口', 2);
|
||||||
conf := _LoadClassInfo(docx.GetPath() + '\\funcext\\TSOffice\\TSUtils\\TOffice.tsf', 'TOffice');
|
conf := _LoadClassInfo(docx.GetPath() + '\\funcext\\TSOffice\\TSUtils\\TOfficeApi.tsf', 'TOffice');
|
||||||
_AddFunctionHelpInfo(docx, '' $ paragraph $ '.1.', conf, 3);
|
_AddFunctionHelpInfo(docx, '' $ paragraph $ '.1.', conf, 3);
|
||||||
|
|
||||||
println(' >>OK\n');
|
println(' >>OK\n');
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
Function _16_Template(docx);
|
||||||
|
Begin
|
||||||
|
paragraph := sysparams['Test'];
|
||||||
|
_PrintMsg('报告模板(ExecInnerTSL)');
|
||||||
|
_AddTitle(docx, 'ExecInnerTSL', 1);
|
||||||
|
|
||||||
|
//添加段落
|
||||||
|
p := TOfficeObj('TParagraph');
|
||||||
|
p.Run.SetText( '系统提供docx.ExecInnerTSL()接口,用户可以制作自定义的报告模板,参考文档:' + 'funcext\\TSOffice\\template\\template.docx。');
|
||||||
|
p.Format.FirstLineIndent := 220; //指定段落第一行缩进的相对差异的值
|
||||||
|
p.Format.LeftIndent := 440;//段落左边距
|
||||||
|
p.Font.Name := '宋体';
|
||||||
|
p.Font.Color := 'FF0000';
|
||||||
|
p.Font.Bold := true;
|
||||||
|
p.Font.Size := 29;
|
||||||
|
p1 := docx.AddParagraph(p, -1, nil);
|
||||||
|
|
||||||
|
println(' >>OK\n');
|
||||||
|
End;
|
||||||
|
|
||||||
Function _AddTitle(docx, subject, level);
|
Function _AddTitle(docx, subject, level);
|
||||||
Begin
|
Begin
|
||||||
leftIndent := array((0,0), (425,425), (453,850), (708,1508));
|
leftIndent := array((0,0), (425,425), (453,850), (708,1508));
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,4 +1,4 @@
|
||||||
// Version 1.0.8
|
// Version 1.0.9
|
||||||
|
|
||||||
Function TOfficeObj(n);
|
Function TOfficeObj(n);
|
||||||
Begin
|
Begin
|
||||||
|
|
@ -1124,7 +1124,7 @@ type TChartImpl=class(NodeInfo)
|
||||||
,("field":"xmlObj","name":"xmlObj","obj":xmlObj,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
,("field":"xmlObj","name":"xmlObj","obj":xmlObj,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
||||||
,("field":"Rid","name":"Rid","obj":Rid,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
,("field":"Rid","name":"Rid","obj":Rid,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
||||||
,("field":"pNode","name":"pNode","obj":pNode,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
,("field":"pNode","name":"pNode","obj":pNode,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
||||||
,("field":"DisableExcel","name":"DisableExcel","obj":DisableExcel,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
,("field":"DisableExcel","name":"DisableExcel","obj":DisableExcel,"attrEx":"","nodeType":"","attrName":"", "desc":"是否内嵌excel数据文件,默认嵌入。", "class":"")
|
||||||
,("field":"Excel","name":"Excel","obj":Excel,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
,("field":"Excel","name":"Excel","obj":Excel,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
||||||
,("field":"chartFileName","name":"chartFileName","obj":chartFileName,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
,("field":"chartFileName","name":"chartFileName","obj":chartFileName,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
||||||
,("field":"excelFileName","name":"excelFileName","obj":excelFileName,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
,("field":"excelFileName","name":"excelFileName","obj":excelFileName,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
||||||
|
|
@ -2193,7 +2193,8 @@ type TdLbls=class(NodeInfo)
|
||||||
Function GetChildren(); override;
|
Function GetChildren(); override;
|
||||||
Begin
|
Begin
|
||||||
HandleChildren();
|
HandleChildren();
|
||||||
return array(("field":"ShowLegendKey","name":"c:showLegendKey","obj":ShowLegendKey,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"")
|
return array(("field":"Del","name":"c:delete","obj":Del,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"")
|
||||||
|
,("field":"ShowLegendKey","name":"c:showLegendKey","obj":ShowLegendKey,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"")
|
||||||
,("field":"ShowVal","name":"c:showVal","obj":ShowVal,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"")
|
,("field":"ShowVal","name":"c:showVal","obj":ShowVal,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"")
|
||||||
,("field":"ShowCatName","name":"c:showCatName","obj":ShowCatName,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"")
|
,("field":"ShowCatName","name":"c:showCatName","obj":ShowCatName,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"")
|
||||||
,("field":"ShowSerName","name":"c:showSerName","obj":ShowSerName,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"")
|
,("field":"ShowSerName","name":"c:showSerName","obj":ShowSerName,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"")
|
||||||
|
|
@ -2206,6 +2207,7 @@ type TdLbls=class(NodeInfo)
|
||||||
//Attributes
|
//Attributes
|
||||||
|
|
||||||
//Nodes
|
//Nodes
|
||||||
|
Del;
|
||||||
ShowLegendKey;
|
ShowLegendKey;
|
||||||
ShowVal;
|
ShowVal;
|
||||||
ShowCatName;
|
ShowCatName;
|
||||||
|
|
@ -9177,10 +9179,10 @@ Type TPicture = Class(DocObject, TPictureImpl)
|
||||||
node := class(TSXml).GetNode(node_,'w:r/w:drawing/wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip');
|
node := class(TSXml).GetNode(node_,'w:r/w:drawing/wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip');
|
||||||
if ifObj(node) then
|
if ifObj(node) then
|
||||||
rid := node.GetAttribute('r:embed');
|
rid := node.GetAttribute('r:embed');
|
||||||
xml := document.ZipObject().Get('word/_rels/document.xml.rels');
|
xml := document.Zip().Get('word/_rels/document.xml.rels');
|
||||||
picFileName := class(TSXml).FindRelationshipTarget(xml, rid);
|
picFileName := class(TSXml).FindRelationshipTarget(xml, rid);
|
||||||
if ifstring(picFileName) then Begin
|
if ifstring(picFileName) then Begin
|
||||||
pic := document.ZipObject().Get('word/' + picFileName);
|
pic := document.Zip().Get('word/' + picFileName);
|
||||||
if ifObj(pic) then
|
if ifObj(pic) then
|
||||||
pic.Data := Image;
|
pic.Data := Image;
|
||||||
End;
|
End;
|
||||||
|
|
@ -9258,13 +9260,14 @@ Type TChart = Class(TChartImpl)
|
||||||
pNode := node;
|
pNode := node;
|
||||||
if not ifObj(cNode) then
|
if not ifObj(cNode) then
|
||||||
return;
|
return;
|
||||||
|
IsWord_ := docx.IsWord();
|
||||||
rId := cNode.GetAttribute('r:id');
|
rId := cNode.GetAttribute('r:id');
|
||||||
relsObj := docx.ZipObject().Get('word/_rels/document.xml.rels');
|
relsObj := docx.Zip().Get('word/_rels/document.xml.rels');
|
||||||
Target := class(TSXml).FindRelationshipTarget(relsObj, rId);
|
Target := class(TSXml).FindRelationshipTarget(relsObj, rId);
|
||||||
if ifNil(Target) then
|
if ifNil(Target) then
|
||||||
return;
|
return;
|
||||||
chartFileName := getChartFileName(Target);
|
chartFileName := getChartFileName(Target);
|
||||||
xmlObj := docx.ZipObject().Get(chartFileName);
|
xmlObj := docx.Zip().Get(chartFileName);
|
||||||
if not ifObj(xmlObj) then
|
if not ifObj(xmlObj) then
|
||||||
return;
|
return;
|
||||||
plotAreaNode := class(TSXml).GetNode(xmlObj, 'c:chartSpace/c:chart/c:plotArea');
|
plotAreaNode := class(TSXml).GetNode(xmlObj, 'c:chartSpace/c:chart/c:plotArea');
|
||||||
|
|
@ -9389,7 +9392,6 @@ Type TChart = Class(TChartImpl)
|
||||||
return;
|
return;
|
||||||
if ifstring(Title) and Title <> '' then
|
if ifstring(Title) and Title <> '' then
|
||||||
UpdateTitle(class(TSXml).CurCodePageToUtf8(Title));
|
UpdateTitle(class(TSXml).CurCodePageToUtf8(Title));
|
||||||
return;
|
|
||||||
//不同的图表,数据区较复杂
|
//不同的图表,数据区较复杂
|
||||||
if not istable(Series) then return;
|
if not istable(Series) then return;
|
||||||
ser := self.C ? 'c:ser' : 'ser';
|
ser := self.C ? 'c:ser' : 'ser';
|
||||||
|
|
@ -9401,26 +9403,116 @@ Type TChart = Class(TChartImpl)
|
||||||
rId := node.GetAttribute('r:id');
|
rId := node.GetAttribute('r:id');
|
||||||
fName := ExtractFileName(chartFileName);
|
fName := ExtractFileName(chartFileName);
|
||||||
rels := 'word/charts/_rels/' + fName + '.rels';
|
rels := 'word/charts/_rels/' + fName + '.rels';
|
||||||
relsObj := docx.ZipObject().Get(rels);
|
chartId := leftstr(fName, length(fName) - 4);
|
||||||
|
chartId := rightstr(chartId, length(chartId) - 5);
|
||||||
|
relsObj := docx.Zip().Get(rels);
|
||||||
if ifObj(relsObj) then Begin
|
if ifObj(relsObj) then Begin
|
||||||
target := FindRelationshipTarget(relsObj, rId);//../embeddings/Workbook2.xlsx
|
target := class(TSXml).FindRelationshipTarget(relsObj, rId);//../embeddings/Workbook2.xlsx
|
||||||
excelFileName := ReplaceStr(target, '..','word');
|
excelFileName := ReplaceStr(target, '..','word');
|
||||||
excelObj := docx.ZipObject().Get(excelFileName);
|
excelObj := docx.Zip().Get(excelFileName);
|
||||||
if ifObj(excelObj) then
|
if ifObj(excelObj) then
|
||||||
NewExcelFile();
|
NewExcelFile();
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
//更新数据区
|
||||||
|
dom := serNode.Marshal();
|
||||||
for i:=0 to length(Series)-1 do Begin
|
for i:=0 to length(Series)-1 do Begin
|
||||||
//<c:tx>
|
if i then
|
||||||
|
serNode := serNode.InsertAfterChild(serNode, dom[0]);
|
||||||
|
removeOldSer(serNode);
|
||||||
|
ser := TOfficeObj('TSer');
|
||||||
|
ser.IDx := i;
|
||||||
|
ser.Ord := i;
|
||||||
|
setTx(ser.Tx.StrRef, Series[i]['Name'], i);
|
||||||
|
n := serNode.FirstChildElement('c:cat');
|
||||||
|
if ifObj(n) then Begin
|
||||||
|
_setCat(ser.Cat, i);
|
||||||
|
_setVal(ser.Val, i);
|
||||||
|
End;
|
||||||
|
|
||||||
|
n := serNode.FirstChildElement('c:xVal');
|
||||||
|
if ifObj(n) then Begin
|
||||||
|
_setCat(ser.XVal, i);
|
||||||
|
_setVal(ser.YVal, i);
|
||||||
|
End;
|
||||||
|
updData := ser.Marshal();
|
||||||
|
class(TSXml).UpdateNode(serNode, updData['attributes'], updData['children']);
|
||||||
End;
|
End;
|
||||||
|
|
||||||
//删除多余的<c:ser>
|
//删除多余的<c:ser>
|
||||||
node := serNode.NextElement(ser);
|
node := serNode.NextElement(ser);
|
||||||
while ifObj(node) do Begin
|
while ifObj(node) do Begin
|
||||||
ChartNode.DeleteChild(node);
|
ChartNode.DeleteChild(node);
|
||||||
node := ChartNode.NextElement(ser);
|
node := serNode.NextElement(ser);
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
//修改内嵌的excel文件
|
||||||
|
AddExcelFile(docx, xmlObj, chartId);
|
||||||
|
End;
|
||||||
|
|
||||||
|
Function removeOldSer(node);
|
||||||
|
Begin
|
||||||
|
task := array('c:tx','c:cat','c:val','c:xVal','c:xYal');
|
||||||
|
for i:=0 to length(task)-1 do begin
|
||||||
|
n := node.FirstChildElement(task[i]);
|
||||||
|
if ifObj(n) then
|
||||||
|
n.DeleteChildren();
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
|
||||||
|
Function AddExcelFile(docx, chartXml, chartId);
|
||||||
|
Begin
|
||||||
|
//内嵌excel数据文件
|
||||||
|
if not ifObj(Excel) then
|
||||||
|
return;
|
||||||
|
[err, data] := Excel.Zip().Save2Mem();
|
||||||
|
if err then
|
||||||
|
return;
|
||||||
|
rId := 'rId1';
|
||||||
|
workBook := 'embeddings/Workbook1.xlsx';
|
||||||
|
fileCnt := 1 + vselect countof( ['FileName'] ) from docx.Zip().Files() where AnsiStartsText('word/embeddings/Workbook', ['FileName']) end;
|
||||||
|
ctXml := docx.Zip().Get('[Content_Types].xml');
|
||||||
|
class(TSXml).AddDefaultContentType(ctXml, 'xlsx', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
||||||
|
externalDataNode := chartXml.FirstChildElement('c:chartSpace').FirstChildElement('c:externalData');
|
||||||
|
if not ifObj(externalDataNode) then
|
||||||
|
chartXml.FirstChildElement('c:chartSpace').InsertEndChild('<c:externalData r:id="rId1"><c:autoUpdate val="0"/></c:externalData>');
|
||||||
|
else Begin
|
||||||
|
rId := externalDataNode.GetAttribute('r:id');
|
||||||
|
End;
|
||||||
|
rels := 'word/charts/_rels/chart' $ chartId $ '.xml.rels';
|
||||||
|
relsObj := docx.Zip().Get(rels);
|
||||||
|
if not ifObj(relsObj) then Begin
|
||||||
|
rId := 'rId1';
|
||||||
|
xmlStr := '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
||||||
|
<Relationship Target="../embeddings/Workbook1.xlsx" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/package" Id="rId1"/>
|
||||||
|
</Relationships>';
|
||||||
|
docx.Zip().Add(rels, xmlStr);
|
||||||
|
if fileCnt > 1 then Begin
|
||||||
|
workBook := 'embeddings/Workbook' $ fileCnt $ '.xlsx';
|
||||||
|
relsObj := docx.Zip().Get(rels);
|
||||||
|
node := relsObj.FirstChildElement('Relationships').FirstChildElement('Relationship');
|
||||||
|
node.SetAttribute('Target', '../' + workBook);
|
||||||
|
End;
|
||||||
|
End
|
||||||
|
else Begin
|
||||||
|
target := class(TSXml).FindRelationshipTarget(relsObj, rId);
|
||||||
|
if ifNil(target) then Begin
|
||||||
|
[maxRid, tg, id] := class(TSXml).FindRelationshipRid(relsObj,'');
|
||||||
|
if fileCnt > 1 then
|
||||||
|
workBook := 'embeddings/Workbook' $ fileCnt $ '.xlsx';
|
||||||
|
maxRid ++;
|
||||||
|
class(TSXml).AddRelationshipRid(relsObj, '../' + workBook, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/package', 'rId' $ maxRid, nil);
|
||||||
|
End
|
||||||
|
else
|
||||||
|
workBook := ReplaceStr(target, '../', '');
|
||||||
|
End;
|
||||||
|
xlsx := docx.Zip().Get('word/' + workBook);
|
||||||
|
if ifObj(xlsx) then
|
||||||
|
xlsx.Data := data; //更新xlsx文件
|
||||||
|
else
|
||||||
|
docx.Zip().Add('word/' + workBook, data); //添加xlsx文件
|
||||||
End;
|
End;
|
||||||
|
|
||||||
///修改图表标题
|
///修改图表标题
|
||||||
|
|
@ -9596,7 +9688,7 @@ private
|
||||||
CatAx.Scaling.Max := XAxis.Max;
|
CatAx.Scaling.Max := XAxis.Max;
|
||||||
CatAx.Scaling.Min := XAxis.Min;
|
CatAx.Scaling.Min := XAxis.Min;
|
||||||
CatAx.Scaling.Orientation := XAxis.ReverseOrder ? 'maxMin' : 'minMax';
|
CatAx.Scaling.Orientation := XAxis.ReverseOrder ? 'maxMin' : 'minMax';
|
||||||
CatAx.Del := XAxis.None;
|
CatAx.Del := 0;//XAxis.None;
|
||||||
CatAx.AxPos := XAxis.ReverseOrder ? 't' : 'b';
|
CatAx.AxPos := XAxis.ReverseOrder ? 't' : 'b';
|
||||||
CatAx.NumFmt.FormatCode := 'General';
|
CatAx.NumFmt.FormatCode := 'General';
|
||||||
CatAx.NumFmt.SourceLinked := true;
|
CatAx.NumFmt.SourceLinked := true;
|
||||||
|
|
@ -9817,7 +9909,8 @@ private
|
||||||
setMarker(ser.Marker, i);
|
setMarker(ser.Marker, i);
|
||||||
setDpt(ser, i);
|
setDpt(ser, i);
|
||||||
//setDLbls(ser.DLbls);
|
//setDLbls(ser.DLbls);
|
||||||
ser.InvertIfNegative := false;
|
//ser.Dlbls.Del := 1;
|
||||||
|
//ser.InvertIfNegative := false;
|
||||||
setCat(ser.Cat, i);
|
setCat(ser.Cat, i);
|
||||||
setVal(ser.Val, i);
|
setVal(ser.Val, i);
|
||||||
setXVal(ser.XVal, i);
|
setXVal(ser.XVal, i);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Version 1.0.8
|
// Version 1.0.9
|
||||||
|
|
||||||
Type TSDocxFile = Class
|
Type TSDocxFile = Class
|
||||||
///Version: V1.0 2022-09-20
|
///Version: V1.0 2022-09-20
|
||||||
|
|
@ -29,7 +29,6 @@ Type TSDocxFile = Class
|
||||||
Begin
|
Begin
|
||||||
DocPrId_ := -1;
|
DocPrId_ := -1;
|
||||||
zipfile_ := new ZipFile();
|
zipfile_ := new ZipFile();
|
||||||
xml_ := new TSXml();
|
|
||||||
End;
|
End;
|
||||||
|
|
||||||
///打开docx文件
|
///打开docx文件
|
||||||
|
|
@ -41,7 +40,7 @@ Type TSDocxFile = Class
|
||||||
if not ifObj(zipfile_) then return array(-1, 'Create ZipFile object fail.');
|
if not ifObj(zipfile_) then return array(-1, 'Create ZipFile object fail.');
|
||||||
[err, errmsg] := zipfile_.Open(alias, fname);
|
[err, errmsg] := zipfile_.Open(alias, fname);
|
||||||
if err=0 then Begin
|
if err=0 then Begin
|
||||||
document_ := new docxDocument(zipfile_, xml_);
|
document_ := new docxDocument(zipfile_);
|
||||||
End;
|
End;
|
||||||
return array(err, errmsg);
|
return array(err, errmsg);
|
||||||
End;
|
End;
|
||||||
|
|
@ -415,11 +414,16 @@ Type TSDocxFile = Class
|
||||||
return Body().ExecInnerTSL(self);
|
return Body().ExecInnerTSL(self);
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Function ZipObject();
|
Function Zip();//兼容excel
|
||||||
Begin
|
Begin
|
||||||
return zipfile_;
|
return zipfile_;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
Function IsWord();
|
||||||
|
Begin
|
||||||
|
return true;
|
||||||
|
End;
|
||||||
|
|
||||||
Function GetPath();
|
Function GetPath();
|
||||||
Begin
|
Begin
|
||||||
return ExtractFileDir(ExtractFileDir(PluginPath()));
|
return ExtractFileDir(ExtractFileDir(PluginPath()));
|
||||||
|
|
@ -456,7 +460,6 @@ private
|
||||||
private
|
private
|
||||||
zipfile_; //压缩文件对象
|
zipfile_; //压缩文件对象
|
||||||
document_; //Document对象
|
document_; //Document对象
|
||||||
xml_; //TSXml对象
|
|
||||||
styleObj_;
|
styleObj_;
|
||||||
numberingObj_;
|
numberingObj_;
|
||||||
DocPrId_;
|
DocPrId_;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Version 1.0.8
|
// Version 1.0.9
|
||||||
|
|
||||||
Type TSExcelFile = Class
|
Type TSExcelFile = Class
|
||||||
///Version: V1.0 2022-08-08
|
///Version: V1.0 2022-08-08
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ public
|
||||||
if ifnil(obj) then continue;
|
if ifnil(obj) then continue;
|
||||||
//find := select thisrowindex as "rowindex_", * from child_arr where ['name'] = children_[i]['name'] end; //优化为循环,性能提高15-20%,2022-12-20
|
//find := select thisrowindex as "rowindex_", * from child_arr where ['name'] = children_[i]['name'] end; //优化为循环,性能提高15-20%,2022-12-20
|
||||||
find := array();
|
find := array();
|
||||||
for j:=0 to length(child_arr)-1 do Begin
|
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
|
if child_arr[j]['name'] = children_[i]['name'] then Begin
|
||||||
find[0] := child_arr[j];
|
find[0] := child_arr[j];
|
||||||
find[0]['rowindex_'] := j;
|
find[0]['rowindex_'] := j;
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,30 @@ Type TOffice = Class
|
||||||
return false;
|
return false;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
///UTF8转当前字符集
|
||||||
|
Function Utf8ToCurCodePage(str);
|
||||||
|
Begin
|
||||||
|
if ifstring(str) and not IsUtf8() then
|
||||||
|
return UTF8ToAnsi(str);
|
||||||
|
return str;
|
||||||
|
End;
|
||||||
|
|
||||||
|
///当前字符集转UTF8
|
||||||
|
Function CurCodePageToUtf8(str);
|
||||||
|
Begin
|
||||||
|
if ifstring(str) and not IsUtf8() then
|
||||||
|
return AnsiToUTF8(str);
|
||||||
|
return str;
|
||||||
|
End;
|
||||||
|
|
||||||
|
///当前字符集转GBK
|
||||||
|
Function CurCodePageToGBK(str);
|
||||||
|
Begin
|
||||||
|
if ifstring(str) and IsUtf8() then
|
||||||
|
return UTF8ToAnsi(str);
|
||||||
|
return str;
|
||||||
|
End;
|
||||||
|
|
||||||
///获得当前文档对象:TDocxFile对象
|
///获得当前文档对象:TDocxFile对象
|
||||||
Function GetDocument();
|
Function GetDocument();
|
||||||
Begin
|
Begin
|
||||||
|
|
|
||||||
|
|
@ -101,8 +101,10 @@ Type TSXml = Class
|
||||||
child := node.FirstChild();
|
child := node.FirstChild();
|
||||||
else
|
else
|
||||||
child := node.FirstChild(children[i]['name']);
|
child := node.FirstChild(children[i]['name']);
|
||||||
if not ifObj(child) then
|
if not ifObj(child) then Begin
|
||||||
child := node.InsertEndChild(children[i]['type'], children[i]['name']);
|
child := node.InsertEndChild(children[i]);
|
||||||
|
continue;
|
||||||
|
End;
|
||||||
if children[i]['type'] = 'pcdata' then
|
if children[i]['type'] = 'pcdata' then
|
||||||
child.SetValue(children[i]['value']);
|
child.SetValue(children[i]['value']);
|
||||||
else
|
else
|
||||||
|
|
@ -324,16 +326,12 @@ Type TSXml = Class
|
||||||
|
|
||||||
class Function Utf8ToCurCodePage(str);
|
class Function Utf8ToCurCodePage(str);
|
||||||
Begin
|
Begin
|
||||||
if ifstring(str) and not class(TSXml).IsUtf8() then
|
return TOfficeApi().Utf8ToCurCodePage(str);
|
||||||
return UTF8ToAnsi(str);
|
|
||||||
return str;
|
|
||||||
End;
|
End;
|
||||||
|
|
||||||
class Function CurCodePageToUtf8(str);
|
class Function CurCodePageToUtf8(str);
|
||||||
Begin
|
Begin
|
||||||
if ifstring(str) and not class(TSXml).IsUtf8() then
|
return TOfficeApi().CurCodePageToUtf8(str);
|
||||||
return AnsiToUTF8(str);
|
|
||||||
return str;
|
|
||||||
End;
|
End;
|
||||||
|
|
||||||
//字体属性
|
//字体属性
|
||||||
|
|
|
||||||
|
|
@ -5,24 +5,24 @@ Type TDocxChart = Class(TSChart)
|
||||||
docx_ := docx;
|
docx_ := docx;
|
||||||
class(TSChart).Create(chartData);
|
class(TSChart).Create(chartData);
|
||||||
//chartN.xml
|
//chartN.xml
|
||||||
chartId_ := 1 + vselect countof( ['FileName'] ) from docx.ZipObject().Files() where AnsiStartsText('word/charts/chart', ['FileName']) end;
|
chartId_ := 1 + vselect countof( ['FileName'] ) from docx.Zip().Files() where AnsiStartsText('word/charts/chart', ['FileName']) end;
|
||||||
targetFileName := 'charts/chart' $ chartId_ $ '.xml';
|
targetFileName := 'charts/chart' $ chartId_ $ '.xml';
|
||||||
chartFile := 'word/' + targetFileName;
|
chartFile := 'word/' + targetFileName;
|
||||||
docx.ZipObject().Add(chartFile, GetDefaultXml());
|
docx.Zip().Add(chartFile, GetDefaultXml());
|
||||||
xmlObj_ := docx.ZipObject().Get(chartFile);
|
xmlObj_ := docx.Zip().Get(chartFile);
|
||||||
if not chartData_.DisableExcel and istable(chartData.Series) and istable(chartData.Series[0]['Categories']) and istable(chartData.Series[0]['Values']) then Begin
|
if not chartData_.DisableExcel and istable(chartData.Series) and istable(chartData.Series[0]['Categories']) and istable(chartData.Series[0]['Values']) then Begin
|
||||||
//chartData_.NewExcelFile();
|
chartData_.NewExcelFile();
|
||||||
End;
|
End;
|
||||||
Apply(xmlObj_);
|
Apply(xmlObj_);
|
||||||
addExternalData();
|
chartData_.AddExcelFile(docx, xmlObj_, chartId_);//添加excel数据文件
|
||||||
|
|
||||||
//Relationship
|
//Relationship
|
||||||
relsObj := docx.ZipObject().Get('word/_rels/document.xml.rels');
|
relsObj := docx.Zip().Get('word/_rels/document.xml.rels');
|
||||||
[rId_, target] := class(TSXml).FindRelationshipRid(relsObj, '');
|
[rId_, target] := class(TSXml).FindRelationshipRid(relsObj, '');
|
||||||
rId_ ++;
|
rId_ ++;
|
||||||
class(TSXml).AddRelationshipRid(relsObj, targetFileName, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', 'rId' $ rId_);
|
class(TSXml).AddRelationshipRid(relsObj, targetFileName, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart', 'rId' $ rId_);
|
||||||
//Content_Types
|
//Content_Types
|
||||||
contentType := docx.ZipObject().Get('[Content_Types].xml');
|
contentType := docx.Zip().Get('[Content_Types].xml');
|
||||||
class(TSXml).AddOverrideContentType(contentType, '/' + chartFile, 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml');
|
class(TSXml).AddOverrideContentType(contentType, '/' + chartFile, 'application/vnd.openxmlformats-officedocument.drawingml.chart+xml');
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
@ -51,31 +51,6 @@ Type TDocxChart = Class(TSChart)
|
||||||
return true;
|
return true;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Function addExternalData();
|
|
||||||
Begin
|
|
||||||
//内嵌excel数据文件
|
|
||||||
if not ifObj(chartData_.Excel) then
|
|
||||||
return;
|
|
||||||
[err, data] := chartData_.Excel.Zip().Save2Mem();
|
|
||||||
if err then
|
|
||||||
return;
|
|
||||||
xmlObj_.FirstChildElement('c:chartSpace').InsertEndChild('<c:externalData r:id="rId1"><c:autoUpdate val="0"/></c:externalData>');
|
|
||||||
rels := 'word/charts/_rels/chart' $ chartId_ $ '.xml.rels';
|
|
||||||
xmlStr := '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
||||||
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
|
||||||
<Relationship Target="../embeddings/Workbook1.xlsx" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/package" Id="rId1"/>
|
|
||||||
</Relationships>';
|
|
||||||
fileCnt := 1 + vselect countof( ['FileName'] ) from docx_.ZipObject().Files() where AnsiStartsText('word/embeddings/Workbook', ['FileName']) end;
|
|
||||||
workBook := 'embeddings/Workbook' $ fileCnt $ '.xlsx';
|
|
||||||
docx_.ZipObject().Add(rels, xmlStr);
|
|
||||||
if fileCnt > 1 then Begin
|
|
||||||
relsObj := docx_.ZipObject().Get(rels);
|
|
||||||
node := relsObj.FirstChildElement('Relationships').FirstChildElement('Relationship');
|
|
||||||
node.SetAttribute('Target', '../' + workBook);
|
|
||||||
End;
|
|
||||||
docx_.ZipObject().Add('word/' + workBook, data);
|
|
||||||
End;
|
|
||||||
|
|
||||||
docx_;
|
docx_;
|
||||||
chartId_;
|
chartId_;
|
||||||
rId_;
|
rId_;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ Type TDocxStyles = Class
|
||||||
Function Create(docx);
|
Function Create(docx);
|
||||||
Begin
|
Begin
|
||||||
docx_ := docx;
|
docx_ := docx;
|
||||||
stylesXml_ := docx.ZipObject().Get('word/styles.xml');
|
stylesXml_ := docx.Zip().Get('word/styles.xml');
|
||||||
idMap_ := array();
|
idMap_ := array();
|
||||||
nameMap_ := array();
|
nameMap_ := array();
|
||||||
maxStyleId_ := 1;
|
maxStyleId_ := 1;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ Type TNumbering = Class
|
||||||
Function Create(docx);
|
Function Create(docx);
|
||||||
Begin
|
Begin
|
||||||
docx_ := docx;
|
docx_ := docx;
|
||||||
numberingXml_ := docx.ZipObject().Get('word/numbering.xml');
|
numberingXml_ := docx.Zip().Get('word/numbering.xml');
|
||||||
if not ifObj(numberingXml_) then Begin
|
if not ifObj(numberingXml_) then Begin
|
||||||
path := docx.GetPath();
|
path := docx.GetPath();
|
||||||
if path[1] = '/' then
|
if path[1] = '/' then
|
||||||
|
|
@ -11,15 +11,15 @@ Type TNumbering = Class
|
||||||
else
|
else
|
||||||
fName := path + '\\funcext\\TSOffice\\template\\numbering\\numbering.xml';
|
fName := path + '\\funcext\\TSOffice\\template\\numbering\\numbering.xml';
|
||||||
if ReadFile(rwraw(), '', fName, 0, 100 * 1024, xmlData) then Begin
|
if ReadFile(rwraw(), '', fName, 0, 100 * 1024, xmlData) then Begin
|
||||||
docx.ZipObject().Add('word/numbering.xml', xmlData);
|
docx.Zip().Add('word/numbering.xml', xmlData);
|
||||||
rels := 'word/_rels/document.xml.rels';
|
rels := 'word/_rels/document.xml.rels';
|
||||||
relsObj := docx.ZipObject().Get(rels);
|
relsObj := docx.Zip().Get(rels);
|
||||||
[rId, target] := class(TSXml).FindRelationshipRid(relsObj, '');
|
[rId, target] := class(TSXml).FindRelationshipRid(relsObj, '');
|
||||||
rId ++;
|
rId ++;
|
||||||
class(TSXml).AddRelationshipRid(relsObj, 'numbering.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering', 'rId' $ rId);
|
class(TSXml).AddRelationshipRid(relsObj, 'numbering.xml', 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering', 'rId' $ rId);
|
||||||
contentType := docx.ZipObject().Get('[Content_Types].xml');
|
contentType := docx.Zip().Get('[Content_Types].xml');
|
||||||
class(TSXml).AddOverrideContentType(contentType, '/word/numbering.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml');
|
class(TSXml).AddOverrideContentType(contentType, '/word/numbering.xml', 'application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml');
|
||||||
numberingXml_ := docx.ZipObject().Get('word/numbering.xml');
|
numberingXml_ := docx.Zip().Get('word/numbering.xml');
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
maxAbstractNumId_ := 0;
|
maxAbstractNumId_ := 0;
|
||||||
|
|
@ -85,7 +85,7 @@ Type TNumbering = Class
|
||||||
///返回:TNumStyle对象
|
///返回:TNumStyle对象
|
||||||
Function NumberStyle(numId);overload;
|
Function NumberStyle(numId);overload;
|
||||||
Begin
|
Begin
|
||||||
abstractNumId := numIdMap_[numId];
|
abstractNumId := numIdMap_['' $ numId];
|
||||||
if abstractNumId then Begin
|
if abstractNumId then Begin
|
||||||
return numStyleObjs_[abstractNumId];
|
return numStyleObjs_[abstractNumId];
|
||||||
End;
|
End;
|
||||||
|
|
@ -208,8 +208,8 @@ Type TNumbering = Class
|
||||||
//生成nsid随机数->转16进制
|
//生成nsid随机数->转16进制
|
||||||
Function _setNsId(o);
|
Function _setNsId(o);
|
||||||
Begin
|
Begin
|
||||||
v := RandomRange(1000000000,2000000000);
|
v := Integer(RandomRange(1000000000,2000000000));
|
||||||
id := tohex(v);
|
id := inttohex(v);
|
||||||
if hash_[id] then
|
if hash_[id] then
|
||||||
return _setNsId(o);
|
return _setNsId(o);
|
||||||
hash_[id] := 1;
|
hash_[id] := 1;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ Type TTableContent = class
|
||||||
impl_ := TOfficeObj('TTableContentImpl');
|
impl_ := TOfficeObj('TTableContentImpl');
|
||||||
//_CheckNodes('endnotes.xml');
|
//_CheckNodes('endnotes.xml');
|
||||||
//_CheckNodes('footnotes.xml');
|
//_CheckNodes('footnotes.xml');
|
||||||
//contentType := docx.ZipObject().Get('[Content_Types].xml');
|
//contentType := docx.Zip().Get('[Content_Types].xml');
|
||||||
//class(TSXml).AddOverrideContentType(contentType, 'wmf', 'image/x-wmf');
|
//class(TSXml).AddOverrideContentType(contentType, 'wmf', 'image/x-wmf');
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
@ -273,7 +273,7 @@ Type TTableContent = class
|
||||||
|
|
||||||
Function _CheckNodes(name);
|
Function _CheckNodes(name);
|
||||||
Begin
|
Begin
|
||||||
z := docx_.ZipObject();
|
z := docx_.Zip();
|
||||||
xml := z.Get('word/' + name);
|
xml := z.Get('word/' + name);
|
||||||
if not ifObj(xml) then Begin
|
if not ifObj(xml) then Begin
|
||||||
path := docx_.GetPath();
|
path := docx_.GetPath();
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,9 @@ Type docxDocument = Class
|
||||||
/// word/document.xml对象
|
/// word/document.xml对象
|
||||||
|
|
||||||
///缺省构造函数
|
///缺省构造函数
|
||||||
Function Create(z,xml); overload;
|
Function Create(z); overload;
|
||||||
Begin
|
Begin
|
||||||
zipfile_ := z;
|
zipfile_ := z;
|
||||||
xml_ := xml;
|
|
||||||
document_ := zipfile_.Get('word/document.xml');
|
document_ := zipfile_.Get('word/document.xml');
|
||||||
root_ := document_.FirstChildElement('w:document');
|
root_ := document_.FirstChildElement('w:document');
|
||||||
bodyNode_ := root_.FirstChildElement('w:body');
|
bodyNode_ := root_.FirstChildElement('w:body');
|
||||||
|
|
@ -44,7 +43,6 @@ Type docxDocument = Class
|
||||||
return bookmarkid_;
|
return bookmarkid_;
|
||||||
End;
|
End;
|
||||||
private
|
private
|
||||||
xml_;
|
|
||||||
root_;//w:document
|
root_;//w:document
|
||||||
bodyNode_;//w:body
|
bodyNode_;//w:body
|
||||||
body_;
|
body_;
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue