v1.3.2
This commit is contained in:
parent
0e21645b2a
commit
c706d2d8d0
|
|
@ -8,9 +8,12 @@ TSOffice 项目:纯 TSL 代码实现 excel、word 文件读写
|
||||||
|
|
||||||
对应文件夹的dll文件按如下要求
|
对应文件夹的dll文件按如下要求
|
||||||
|
|
||||||
- `fmt_pubkrnl_plugin` 放入 tsl 安装根目录下 Plugin 文件夹
|
|
||||||
- `office_plugin` 放入 tsl 安装根目录下 Plugin 文件夹
|
- `office_plugin` 放入 tsl 安装根目录下 Plugin 文件夹
|
||||||
|
|
||||||
|
可选:
|
||||||
|
|
||||||
|
- `fmt_pubkrnl_plugin` 放入 tsl 安装根目录下 Plugin 文件夹,若需要执行Demo文件夹下的[ExcelHelp.tsl](./Demo/ExcelHelp.tsl)和[WordHelp.tsl](./Demo/WordHelp.tsl),需要部署改动态库
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
根据架构选择aarch64或x86版本将对应文件夹内容进行部署
|
根据架构选择aarch64或x86版本将对应文件夹内容进行部署
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
// Version 1.3.0
|
// Version 1.3.2
|
||||||
|
|
||||||
Function TOfficeObj(n);
|
Function TOfficeObj(n);
|
||||||
Begin
|
Begin
|
||||||
case lowercase(n) of
|
case lowercase(n) of
|
||||||
"nodeinfo":
|
"nodeinfo":
|
||||||
return new NodeInfo("");
|
return new NodeInfo("");
|
||||||
|
"trange":
|
||||||
|
return new TRange("");
|
||||||
"tfont":
|
"tfont":
|
||||||
return new TFont();
|
return new TFont();
|
||||||
"tcomment":
|
"tcomment":
|
||||||
|
|
@ -1353,6 +1355,7 @@ type TChartImpl=class(NodeInfo)
|
||||||
,("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":"")
|
||||||
|
,("field":"drawingFileName","name":"drawingFileName","obj":drawingFileName,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"")
|
||||||
) union ExtNodes;
|
) union ExtNodes;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
@ -1395,6 +1398,7 @@ type TChartImpl=class(NodeInfo)
|
||||||
Excel;
|
Excel;
|
||||||
chartFileName;
|
chartFileName;
|
||||||
excelFileName;
|
excelFileName;
|
||||||
|
drawingFileName;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
|
|
@ -9933,7 +9937,7 @@ type TProtect=class(NodeInfo)
|
||||||
Function GetAttrs(); override;
|
Function GetAttrs(); override;
|
||||||
Begin
|
Begin
|
||||||
HandleAttrs();
|
HandleAttrs();
|
||||||
return array(("Sheet", "sheet", Sheet, ""),("EditObjects", "objects", EditObjects, ""),("EditScenarios", "scenarios", EditScenarios, ""),("FormatCells", "formatCells", FormatCells, ""),("FormatColumns", "formatColumns", FormatColumns, ""),("FormatRows", "formatRows", FormatRows, ""),("InsertColumns", "insertColumns", InsertColumns, ""),("InsertRows", "insertRows", InsertRows, ""),("InsertHyperlinks", "insertHyperlinks", InsertHyperlinks, ""),("DeleteColumns", "deleteColumns", DeleteColumns, ""),("DeleteRows", "deleteRows", DeleteRows, ""),("SelectLockedCells", "selectLockedCells", SelectLockedCells, ""),("Sort", "sort", Sort, ""),("AutoFilter", "autoFilter", AutoFilter, ""),("PivotTables", "pivotTables", PivotTables, ""),("SelectUnLockedCells", "selectUnlockedCells", SelectUnLockedCells, "")) union ExtAttr;
|
return array(("Password", "password", Password, ""),("AlgorithmName", "algorithmName", AlgorithmName, ""),("HashValue", "hashValue", HashValue, ""),("SaltValue", "saltValue", SaltValue, ""),("SpinCount", "spinCount", SpinCount, ""),("Sheet", "sheet", Sheet, ""),("EditObjects", "objects", EditObjects, ""),("EditScenarios", "scenarios", EditScenarios, ""),("FormatCells", "formatCells", FormatCells, ""),("FormatColumns", "formatColumns", FormatColumns, ""),("FormatRows", "formatRows", FormatRows, ""),("InsertColumns", "insertColumns", InsertColumns, ""),("InsertRows", "insertRows", InsertRows, ""),("InsertHyperlinks", "insertHyperlinks", InsertHyperlinks, ""),("DeleteColumns", "deleteColumns", DeleteColumns, ""),("DeleteRows", "deleteRows", DeleteRows, ""),("SelectLockedCells", "selectLockedCells", SelectLockedCells, ""),("Sort", "sort", Sort, ""),("AutoFilter", "autoFilter", AutoFilter, ""),("PivotTables", "pivotTables", PivotTables, ""),("SelectUnLockedCells", "selectUnlockedCells", SelectUnLockedCells, "")) union ExtAttr;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Function GetChildren(); override;
|
Function GetChildren(); override;
|
||||||
|
|
@ -9943,6 +9947,11 @@ type TProtect=class(NodeInfo)
|
||||||
End;
|
End;
|
||||||
|
|
||||||
//Attributes
|
//Attributes
|
||||||
|
Password;
|
||||||
|
AlgorithmName;
|
||||||
|
HashValue;
|
||||||
|
SaltValue;
|
||||||
|
SpinCount;
|
||||||
Sheet;
|
Sheet;
|
||||||
EditObjects;
|
EditObjects;
|
||||||
EditScenarios;
|
EditScenarios;
|
||||||
|
|
@ -10149,11 +10158,20 @@ End;
|
||||||
///DOCX文档实现
|
///DOCX文档实现
|
||||||
|
|
||||||
Type TRange = Class
|
Type TRange = Class
|
||||||
Function Create(t);
|
Function Create();overload;
|
||||||
|
Begin
|
||||||
|
Create(nil);
|
||||||
|
End;
|
||||||
|
|
||||||
|
Function Create(t);overload;
|
||||||
Begin
|
Begin
|
||||||
//array(("pNode":nodeObj, "pIndex":p, "rNode":nodeObj, "rIndex":r))
|
//array(("pNode":nodeObj, "pIndex":p, "rNode":nodeObj, "rIndex":r))
|
||||||
|
Init(t);
|
||||||
|
End;
|
||||||
|
|
||||||
|
Function Init(t);
|
||||||
|
Begin
|
||||||
RunArr_ := t;
|
RunArr_ := t;
|
||||||
rPr_ := new TwrPr();
|
|
||||||
End;
|
End;
|
||||||
|
|
||||||
///清除全部选中内容
|
///清除全部选中内容
|
||||||
|
|
@ -10165,6 +10183,8 @@ Type TRange = Class
|
||||||
Property Font read readFont;
|
Property Font read readFont;
|
||||||
Function readFont();
|
Function readFont();
|
||||||
Begin
|
Begin
|
||||||
|
if ifNil(rPr_) then
|
||||||
|
rPr_ := new TwrPr();
|
||||||
return rPr_;
|
return rPr_;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
@ -10186,6 +10206,7 @@ Type TRange = Class
|
||||||
///应用字体样式
|
///应用字体样式
|
||||||
Function Apply();
|
Function Apply();
|
||||||
Begin
|
Begin
|
||||||
|
if not ifObj(rPr_) then return;
|
||||||
arr := rPr_.Marshal();
|
arr := rPr_.Marshal();
|
||||||
if length(arr['attributes']) or length(arr['children']) then Begin
|
if length(arr['attributes']) or length(arr['children']) then Begin
|
||||||
for i:=0 to length(RunArr_)-1 do Begin
|
for i:=0 to length(RunArr_)-1 do Begin
|
||||||
|
|
@ -10197,11 +10218,9 @@ Type TRange = Class
|
||||||
|
|
||||||
Function _clear(first);
|
Function _clear(first);
|
||||||
Begin
|
Begin
|
||||||
for i:=first to length(RunArr_)-1 do Begin
|
|
||||||
RunArr_[i]['pNode'].DeleteChild(RunArr_[i]['rNode']);
|
|
||||||
End;
|
|
||||||
for i:=first to length(RunArr_)-1 do Begin
|
for i:=first to length(RunArr_)-1 do Begin
|
||||||
pNode := RunArr_[i]['pNode'];
|
pNode := RunArr_[i]['pNode'];
|
||||||
|
pNode.DeleteChild(RunArr_[i]['rNode']);
|
||||||
rNode := pNode.FirstChildElement('w:r');
|
rNode := pNode.FirstChildElement('w:r');
|
||||||
if not ifObj(rNode) then
|
if not ifObj(rNode) then
|
||||||
pNode.Parent().DeleteChild(pNode);
|
pNode.Parent().DeleteChild(pNode);
|
||||||
|
|
@ -11323,20 +11342,22 @@ Type TPicture = Class(DocObject, TPictureImpl)
|
||||||
ETU := 360045;//1cm单位
|
ETU := 360045;//1cm单位
|
||||||
maxX := 17.0;//水平方向17cm
|
maxX := 17.0;//水平方向17cm
|
||||||
maxY := 23.0;//垂直方向23cm
|
maxY := 23.0;//垂直方向23cm
|
||||||
|
imageW := image.Width() / 28.346 * ETU;
|
||||||
|
imageH := image.Height() / 28.346 * ETU;
|
||||||
if Width <= 0 and Height <= 0 then Begin //图像缺省大小
|
if Width <= 0 and Height <= 0 then Begin //图像缺省大小
|
||||||
widthVal := image.Width();
|
widthVal := imageW;
|
||||||
heightVal := image.Height();
|
heightVal := imageH;
|
||||||
End
|
End
|
||||||
else Begin //用户设置了图片尺寸
|
else Begin //用户设置了图片尺寸
|
||||||
widthVal := ETU * Width;
|
widthVal := ETU * Width;
|
||||||
heightVal := ETU * Height;
|
heightVal := ETU * Height;
|
||||||
if Width <= 0 and image.Height() and image.Width() then Begin //按照图片比例自动缩放
|
if Width <= 0 and imageH and imageW then Begin //按照图片比例自动缩放
|
||||||
scaling_factor := image.Width() / image.Height();
|
scaling_factor := imageW / imageH;
|
||||||
widthVal := round(heightVal * scaling_factor);
|
widthVal := round(heightVal * scaling_factor);
|
||||||
End;
|
End;
|
||||||
|
|
||||||
if Height <= 0 and image.Height() and image.Width() then Begin //按照图片比例自动缩放
|
if Height <= 0 and imageH and imageW then Begin //按照图片比例自动缩放
|
||||||
scaling_factor := image.Width() / image.Height();
|
scaling_factor := imageW / imageH;
|
||||||
heightVal := round(widthVal / scaling_factor);
|
heightVal := round(widthVal / scaling_factor);
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
|
|
@ -11361,7 +11382,7 @@ Type TPicture = Class(DocObject, TPictureImpl)
|
||||||
heightVal *= ratio;
|
heightVal *= ratio;
|
||||||
widthVal *= ratio;
|
widthVal *= ratio;
|
||||||
End;
|
End;
|
||||||
//println('w={}-{},maxx={}, h={}-{},maxh={},ratio={}',integer(image.Width()),integer(widthVal),15 * ETU, integer(image.Height()),integer(heightVal),23 * ETU,ratio);
|
//println('w={}-{},maxx={}, h={}-{},maxh={},ratio={}',integer(imageW),integer(widthVal),15 * ETU, integer(imageH),integer(heightVal),23 * ETU,ratio);
|
||||||
return array(integer(widthVal), integer(heightVal));
|
return array(integer(widthVal), integer(heightVal));
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
@ -12112,7 +12133,7 @@ private
|
||||||
cnt := length(data);
|
cnt := length(data);
|
||||||
//[err, axis] := ColumnNumberToName(2 * ind + 2);
|
//[err, axis] := ColumnNumberToName(2 * ind + 2);
|
||||||
[err, axis] := ColumnNumberToName(ind + 2);
|
[err, axis] := ColumnNumberToName(ind + 2);
|
||||||
Val.NumRef.F := fmt('Sheet1!${}$2:${}${}',axis, axis, cnt+1);
|
Val.NumRef.F := format('Sheet1!$%s$2:$%s$%d', axis, axis, cnt+1);
|
||||||
Val.NumRef.NumCache.PtCount := cnt;
|
Val.NumRef.NumCache.PtCount := cnt;
|
||||||
Val.NumRef.NumCache.formatCode := 'General';
|
Val.NumRef.NumCache.formatCode := 'General';
|
||||||
for i:=0 to cnt-1 do Begin
|
for i:=0 to cnt-1 do Begin
|
||||||
|
|
@ -12141,8 +12162,7 @@ private
|
||||||
else if istable(Categories) then Begin //word 图表
|
else if istable(Categories) then Begin //word 图表
|
||||||
cnt := length(Categories);
|
cnt := length(Categories);
|
||||||
//[err, axis] := ColumnNumberToName(2 * ind + 1);
|
//[err, axis] := ColumnNumberToName(2 * ind + 1);
|
||||||
//cat.StrRef.F := fmt('Sheet1!${}$2:${}${}',axis, axis, cnt+1);
|
cat.StrRef.F := format('Sheet1!$A$2:$A$%d', cnt+1);
|
||||||
cat.StrRef.F := fmt('Sheet1!$A$2:$A${}', cnt+1);
|
|
||||||
cat.StrRef.StrCache.PtCount := cnt;
|
cat.StrRef.StrCache.PtCount := cnt;
|
||||||
for i:=0 to cnt-1 do Begin
|
for i:=0 to cnt-1 do Begin
|
||||||
Tpt := TOfficeObj('Tpt');
|
Tpt := TOfficeObj('Tpt');
|
||||||
|
|
@ -12946,6 +12966,7 @@ Type TDocumentBody = Class(DocObject)
|
||||||
Function InsertTable(tbl, posOpt);
|
Function InsertTable(tbl, posOpt);
|
||||||
Begin
|
Begin
|
||||||
addPart(posOpt, tbl);
|
addPart(posOpt, tbl);
|
||||||
|
TOfficeApi().Set('CurrentTable', tbl.node_);
|
||||||
tblBorders := class(TSXml).GetNode(tbl.node_, 'w:tblPr/w:tblBorders');
|
tblBorders := class(TSXml).GetNode(tbl.node_, 'w:tblPr/w:tblBorders');
|
||||||
tblCellMar := class(TSXml).GetNode(tbl.node_, 'w:tblPr/w:tblCellMar');
|
tblCellMar := class(TSXml).GetNode(tbl.node_, 'w:tblPr/w:tblCellMar');
|
||||||
if ifObj(tblBorders) or ifObj(tblCellMar) then Begin
|
if ifObj(tblBorders) or ifObj(tblCellMar) then Begin
|
||||||
|
|
@ -13107,6 +13128,7 @@ Type TDocumentBody = Class(DocObject)
|
||||||
|
|
||||||
p := new TPicture(picture.node_);
|
p := new TPicture(picture.node_);
|
||||||
_set_lastParagraph_(posOpt, picture.node_);
|
_set_lastParagraph_(posOpt, picture.node_);
|
||||||
|
TOfficeApi().Set('CurrentShape', picture.node_);
|
||||||
return p;
|
return p;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
@ -13268,8 +13290,9 @@ Type TDocumentBody = Class(DocObject)
|
||||||
begParagraphIndex := -1;
|
begParagraphIndex := -1;
|
||||||
begPos := 0;
|
begPos := 0;
|
||||||
begTxtLen := 0;
|
begTxtLen := 0;
|
||||||
for i:=0 to length(tArr)-1 do Begin
|
while i < length(tArr) do Begin
|
||||||
txt := '';
|
txt := '';
|
||||||
|
iStep := 1;
|
||||||
if ifObj(tArr[i]['rNode']) then Begin
|
if ifObj(tArr[i]['rNode']) then Begin
|
||||||
run := new TRun(tArr[i]['rNode']);
|
run := new TRun(tArr[i]['rNode']);
|
||||||
txt := run.Text();
|
txt := run.Text();
|
||||||
|
|
@ -13342,7 +13365,8 @@ Type TDocumentBody = Class(DocObject)
|
||||||
flag := '[TSL]';
|
flag := '[TSL]';
|
||||||
'[TSL][/TSL':
|
'[TSL][/TSL':
|
||||||
if c = ']' then Begin
|
if c = ']' then Begin
|
||||||
curParagraphNode := tslArr[0]['pNode'];
|
tslBegParagraphNode := tslArr[0]['pNode'];
|
||||||
|
tslEndParagraphNode := tArr[i]['pNode'];
|
||||||
ind := length(tslArr) - 1;
|
ind := length(tslArr) - 1;
|
||||||
if tslArr[ind]['pIndex'] <> tArr[i]['pIndex'] or tslArr[ind]['rIndex'] <> tArr[i]['rIndex'] then Begin
|
if tslArr[ind]['pIndex'] <> tArr[i]['pIndex'] or tslArr[ind]['rIndex'] <> tArr[i]['rIndex'] then Begin
|
||||||
ind ++;
|
ind ++;
|
||||||
|
|
@ -13359,7 +13383,7 @@ Type TDocumentBody = Class(DocObject)
|
||||||
oldNode := prevRun;
|
oldNode := prevRun;
|
||||||
tArr[i]['rNode'] := run._duplicate_r(oldNode);
|
tArr[i]['rNode'] := run._duplicate_r(oldNode);
|
||||||
run._adjust_r(tArr[i]['rNode'], wz, txtLen);
|
run._adjust_r(tArr[i]['rNode'], wz, txtLen);
|
||||||
i--;
|
iStep := 0;
|
||||||
End;
|
End;
|
||||||
curRunNode := tslArr[0]['rNode'];
|
curRunNode := tslArr[0]['rNode'];
|
||||||
curRun := new TRun(curRunNode);
|
curRun := new TRun(curRunNode);
|
||||||
|
|
@ -13382,84 +13406,68 @@ Type TDocumentBody = Class(DocObject)
|
||||||
code := leftstr(code, lengthW(code) - 5 - endPos);
|
code := leftstr(code, lengthW(code) - 5 - endPos);
|
||||||
CodePage := TOfficeApi().Get('CodePage');
|
CodePage := TOfficeApi().Get('CodePage');
|
||||||
TOfficeApi().Set('Docx', docx);
|
TOfficeApi().Set('Docx', docx);
|
||||||
TOfficeApi().Set('CurrentParagraph', curParagraphNode);
|
TOfficeApi().Set('CurrentParagraph', tslBegParagraphNode);
|
||||||
|
TOfficeApi().Set('CurrentPosition', tslBegParagraphNode);
|
||||||
TOfficeApi().Set('CurrentRun', curRunNode);
|
TOfficeApi().Set('CurrentRun', curRunNode);
|
||||||
TOfficeApi().Set('CodePage', 'gbk');
|
TOfficeApi().Set('CodePage', 'gbk');
|
||||||
try
|
try
|
||||||
tslFuncCount ++;
|
tslFuncCount ++;
|
||||||
|
echo format('run code=[%s]\n',code);
|
||||||
if code <> '' then
|
if code <> '' then
|
||||||
str := eval(&code);
|
eval(&code);
|
||||||
except
|
except
|
||||||
println('run code={},err={}', code, ExceptObject.ErrInfo);
|
echo format('run code=%s,err=%s\n', code, ExceptObject.ErrInfo);
|
||||||
errArr[ length(errArr) ] := array('code':code, 'err':ExceptObject.ErrInfo);
|
errArr[ length(errArr) ] := array('code':code, 'err':ExceptObject.ErrInfo);
|
||||||
str := '';
|
|
||||||
End;
|
End;
|
||||||
tNode := curRun.node_.FirstChildElement('w:t');
|
tNode := curRun.node_.FirstChildElement('w:t');
|
||||||
if not ifObj(tNode) then Begin //没有在外部插入文字
|
if not ifObj(tNode) then Begin //没有在外部插入文字
|
||||||
if not ifstring(str) or str = '' then Begin //删除w:r
|
tslBegParagraphNode.DeleteChild(curRunNode);
|
||||||
curParagraphNode.DeleteChild(curRunNode);
|
//兼容WordTemplate函数,不删除空段落(TSL脚本段落)
|
||||||
hasrNode := curParagraphNode.FirstChildElement('w:r');
|
//hasrNode := tslBegParagraphNode.FirstChildElement('w:r');
|
||||||
if not ifObj(hasrNode) then Begin//删除空段落
|
//if not ifObj(hasrNode) then Begin//删除空段落
|
||||||
curParagraphNode.Parent().DeleteChild(curParagraphNode);
|
// tslBegParagraphNode.Parent().DeleteChild(tslBegParagraphNode);
|
||||||
curParagraphNode := nil;
|
// tslBegParagraphNode := nil;
|
||||||
End;
|
//End;
|
||||||
End
|
End;
|
||||||
else Begin
|
//段落炸裂
|
||||||
str := AnsiToUTF8(str);
|
curPosotion := TOfficeApi().Get('CurrentPosition');
|
||||||
lines := str2array(str, '\r\n');
|
if i+iStep < length(tArr) and tArr[i+iStep]['pNode'] = tslEndParagraphNode and tslBegParagraphNode <> curPosotion then Begin
|
||||||
lineCnt := length(lines);
|
data := tslEndParagraphNode.Marshal();
|
||||||
if lineCnt = 1 then Begin //单行
|
NewParagraphNode := tslEndParagraphNode.Parent().InsertAfterChild(curPosotion, data[0]);//复制段落
|
||||||
curRun.SetText(str, true);
|
rmvArr := array();
|
||||||
|
cnt := 0;
|
||||||
|
curLine := 0;
|
||||||
|
prevRNode := tArr[i+iStep]['rNode'].PrevElement('w:r');
|
||||||
|
while ifObj(prevRNode) do Begin
|
||||||
|
curLine ++;
|
||||||
|
prevRNode := prevRNode.PrevElement('w:r');
|
||||||
|
End;
|
||||||
|
rmvN := 0;
|
||||||
|
nextRNode := tArr[i+iStep]['rNode'];
|
||||||
|
while ifObj(nextRNode) do Begin
|
||||||
|
rmvArr[rmvN++] := nextRNode;
|
||||||
|
nextRNode := nextRNode.NextElement('w:r');
|
||||||
|
End;
|
||||||
|
rNode := NewParagraphNode.FirstChildElement('w:r');
|
||||||
|
nI := 0;
|
||||||
|
rIndex := 0;
|
||||||
|
while ifObj(rNode) do Begin
|
||||||
|
cnt ++;
|
||||||
|
if cnt <= curLine then Begin
|
||||||
|
rmvArr[rmvN++] := rNode;
|
||||||
End
|
End
|
||||||
else Begin //多行
|
else Begin
|
||||||
curRun.SetText(lines[0], true);
|
tArr[i+iStep+nI]['pNode'] := NewParagraphNode;
|
||||||
nextRun := curRun.node_.NextElement('w:r');
|
tArr[i+iStep+nI]['rNode'] := rNode;
|
||||||
if ifObj(nextRun) then Begin //段落炸裂
|
tArr[i+iStep+nI]['rIndex'] := rIndex++;
|
||||||
curLine := 0;
|
nr := new TRun(tArr[i+iStep+nI]['rNode']);
|
||||||
prevRNode := curRunNode;
|
nI ++;
|
||||||
while ifObj(prevRNode) do Begin
|
|
||||||
curLine ++;
|
|
||||||
prevRNode := prevRNode.PrevElement('w:r');
|
|
||||||
End;
|
|
||||||
data := curParagraphNode.Marshal();
|
|
||||||
LastParagraphNode := curParagraphNode.Parent().InsertAfterChild(curParagraphNode, data[0]);//复制段落
|
|
||||||
rmvArr := array();
|
|
||||||
cnt := 0;
|
|
||||||
rNode := LastParagraphNode.FirstChildElement('w:r');
|
|
||||||
while ifObj(rNode) do Begin
|
|
||||||
cnt ++;
|
|
||||||
if cnt < curLine then
|
|
||||||
rmvArr[rmvN++] := rNode;
|
|
||||||
else if cnt = curLine then Begin
|
|
||||||
rNode.ClearText();
|
|
||||||
rNode.SetText(lines[lineCnt-1], true);
|
|
||||||
lineCnt--;
|
|
||||||
End;
|
|
||||||
rNode := rNode.NextElement('w:r');
|
|
||||||
End;
|
|
||||||
cnt := 0;
|
|
||||||
rNode := curParagraphNode.FirstChildElement('w:r');
|
|
||||||
while ifObj(rNode) do Begin
|
|
||||||
cnt ++;
|
|
||||||
if cnt > curLine then
|
|
||||||
rmvArr[rmvN++] := rNode;
|
|
||||||
rNode := rNode.NextElement('w:r');
|
|
||||||
End;
|
|
||||||
//删除重复的run
|
|
||||||
for rmvN := 0 to rmvN < length(rmvArr)-1 do begin
|
|
||||||
rmvArr[rmvN].Parent().DeleteChild(rmvArr[rmvN]);
|
|
||||||
End;
|
|
||||||
End;//段落炸裂
|
|
||||||
curParagraph := new TParagraph(curParagraphNode);
|
|
||||||
prev := curParagraph;
|
|
||||||
for nP:=1 to lineCnt - 1 do Begin //新段落
|
|
||||||
if lines[nP]='' then continue;
|
|
||||||
p := new TParagraph();
|
|
||||||
p.Run.SetText(lines[nP], true);
|
|
||||||
prev := docx.AddParagraph(p, prev.Node());
|
|
||||||
docx.CopyFormat(curParagraph, prev);//格式刷
|
|
||||||
End;
|
|
||||||
End;
|
End;
|
||||||
|
rNode := rNode.NextElement('w:r');
|
||||||
|
End;
|
||||||
|
//删除重复的run
|
||||||
|
for rmvN := 0 to length(rmvArr)-1 do begin
|
||||||
|
rmvArr[rmvN].Parent().DeleteChild(rmvArr[rmvN]);
|
||||||
End;
|
End;
|
||||||
End;
|
End;
|
||||||
TOfficeApi().Set('CodePage', CodePage);
|
TOfficeApi().Set('CodePage', CodePage);
|
||||||
|
|
@ -13467,7 +13475,7 @@ Type TDocumentBody = Class(DocObject)
|
||||||
flag := '';
|
flag := '';
|
||||||
code := nil;
|
code := nil;
|
||||||
tslArr := array();
|
tslArr := array();
|
||||||
continue;
|
break;
|
||||||
End
|
End
|
||||||
else
|
else
|
||||||
flag := '[TSL]';
|
flag := '[TSL]';
|
||||||
|
|
@ -13492,10 +13500,232 @@ Type TDocumentBody = Class(DocObject)
|
||||||
if tslArr[ind]['pIndex'] <> tArr[i]['pIndex'] or tslArr[ind]['rIndex'] <> tArr[i]['rIndex'] then
|
if tslArr[ind]['pIndex'] <> tArr[i]['pIndex'] or tslArr[ind]['rIndex'] <> tArr[i]['rIndex'] then
|
||||||
tslArr[ind + 1] := tArr[i];
|
tslArr[ind + 1] := tArr[i];
|
||||||
End;
|
End;
|
||||||
|
i += iStep;
|
||||||
End;
|
End;
|
||||||
return array(length(errArr), tslFuncCount, errArr);
|
return array(length(errArr), tslFuncCount, errArr);
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
Function ExecTsTag(docx, tagName, tagObj);
|
||||||
|
Begin
|
||||||
|
//表格
|
||||||
|
t := array();
|
||||||
|
tslTagCount := 0;
|
||||||
|
errArr := array();
|
||||||
|
tArr := Tables();
|
||||||
|
for i:=0 to length(tArr)-1 do Begin
|
||||||
|
col := tArr[i].Cols();
|
||||||
|
row := tArr[i].Rows();
|
||||||
|
for r:= 1 to row do Begin
|
||||||
|
for c:=1 to col do Begin
|
||||||
|
cell := tArr[i].Cell(r, c);
|
||||||
|
[err, cnt, err] := cell.ExecTsTag(docx, tagName, tagObj);//递归
|
||||||
|
tslTagCount += cnt;
|
||||||
|
errArr union= err;
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
|
||||||
|
//文本框
|
||||||
|
ps := Paragraphs();
|
||||||
|
for i:=0 to length(ps)-1 do Begin
|
||||||
|
boxs := ps[i].TextBoxs();
|
||||||
|
for j:=0 to length(boxs)-1 do Begin
|
||||||
|
[err, cnt, err] := boxs[j].ExecTsTag(docx, tagName, tagObj);//递归
|
||||||
|
if cnt then
|
||||||
|
boxs[j].Apply();
|
||||||
|
tslTagCount += cnt;
|
||||||
|
errArr union= err;
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
|
||||||
|
//页脚、页眉
|
||||||
|
sArr := Sections();
|
||||||
|
tpArr := array('default','even','first');
|
||||||
|
for i:=0 to length(sArr)-1 do Begin
|
||||||
|
for k, name in tpArr do Begin
|
||||||
|
h := sArr[i].Header(name);
|
||||||
|
if ifObj(h) then Begin
|
||||||
|
[err, cnt, err] := h.ExecTsTag(docx, tagName, tagObj);//递归
|
||||||
|
tslTagCount += cnt;
|
||||||
|
errArr union= err;
|
||||||
|
End;
|
||||||
|
|
||||||
|
f := sArr[i].Footer(name);
|
||||||
|
if ifObj(f) then Begin
|
||||||
|
[err, cnt, err] := f.ExecTsTag(docx, tagName, tagObj);//递归
|
||||||
|
tslTagCount += cnt;
|
||||||
|
errArr union= err;
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
|
||||||
|
[err, cnt, err] := ExecTsTagImpl(docx, tagName, tagObj);
|
||||||
|
tslTagCount += cnt;
|
||||||
|
errArr union= err;
|
||||||
|
return array(length(errArr), tslTagCount, errArr);
|
||||||
|
End;
|
||||||
|
|
||||||
|
Function ExecTsTagImpl(docx, tagName, tagObj);
|
||||||
|
Begin
|
||||||
|
tslTagCount := 0;
|
||||||
|
errArr := array();
|
||||||
|
tagArr := array();
|
||||||
|
tArr := TextArray();
|
||||||
|
tagAttribute := '';
|
||||||
|
tagStr := '';
|
||||||
|
tagStatus := '';//array('','head', 'attribute', 'tail');
|
||||||
|
tagHead := '[' + tagName;
|
||||||
|
tagTail := '[/' + tagName;
|
||||||
|
tmp := array();
|
||||||
|
while i < length(tArr) do Begin
|
||||||
|
txt := '';
|
||||||
|
iStep := 1;
|
||||||
|
if ifObj(tArr[i]['rNode']) then Begin
|
||||||
|
run := new TRun(tArr[i]['rNode']);
|
||||||
|
txt := run.Text();
|
||||||
|
if class(TSXml).IsUtf8() then
|
||||||
|
txt := UTF8ToAnsi(txt);
|
||||||
|
End;
|
||||||
|
k := 1;
|
||||||
|
wz := 1;
|
||||||
|
txtLen := length(txt);
|
||||||
|
while k <= txtLen do Begin
|
||||||
|
c := txt[k];
|
||||||
|
if c = ']' and (tagStatus = 'head' or tagStatus = 'attribute') and tagStr = tagHead then Begin //TAG头结束标志
|
||||||
|
tagStr := '';
|
||||||
|
tagArr := tArr[tmp['head-begin-paragraph']:i,:];
|
||||||
|
wz++;
|
||||||
|
tagStatus := 'tail';
|
||||||
|
tmp['head-end-paragraph'] := i;
|
||||||
|
tmp['head-end-pos'] := k++;
|
||||||
|
tmp['head-end-wz'] := wz;
|
||||||
|
tmp['head-end-txtlen'] := txtLen;
|
||||||
|
continue;
|
||||||
|
End;
|
||||||
|
case tagStatus of
|
||||||
|
'':
|
||||||
|
if c = '[' then Begin
|
||||||
|
tagStr := '[';
|
||||||
|
tmp['head-begin-paragraph'] := i;
|
||||||
|
tmp['head-begin-pos'] := k;
|
||||||
|
tmp['head-begin-wz'] := wz;
|
||||||
|
tmp['head-begin-txtlen'] := txtLen;
|
||||||
|
tagStatus := 'head';
|
||||||
|
tagAttribute := '';
|
||||||
|
End;
|
||||||
|
'head':
|
||||||
|
if c = ' ' and tagStr = tagHead then Begin //找到TAG属性
|
||||||
|
tagStatus := 'attribute';
|
||||||
|
End
|
||||||
|
else if length(tagStr) < length(tagHead) and lowercase(c) = lowercase(tagHead[ length(tagStr) + 1 ]) then Begin
|
||||||
|
tagStr += tagHead[ length(tagStr) + 1 ];
|
||||||
|
End
|
||||||
|
else //继续寻找TAG开始标志
|
||||||
|
tagStatus := '';
|
||||||
|
'attribute':
|
||||||
|
tagAttribute += c;
|
||||||
|
'tail':
|
||||||
|
if c=']' and tagStr = tagTail then Begin //查找到完整标签
|
||||||
|
ind := length(tagArr) - 1;
|
||||||
|
if tagArr[ind]['pIndex'] <> tArr[i]['pIndex'] or tagArr[ind]['rIndex'] <> tArr[i]['rIndex'] then Begin
|
||||||
|
ind ++;
|
||||||
|
tagArr[ind] := tArr[i];
|
||||||
|
End;
|
||||||
|
|
||||||
|
//[/tag]后
|
||||||
|
if k < txtLen then Begin //后面分割为新的w:r
|
||||||
|
tArr[i]['rNode'] := run._duplicate_r(tArr[i]['rNode']);
|
||||||
|
run._adjust_r(tArr[i]['rNode'], wz, txtLen);
|
||||||
|
iStep := 0;
|
||||||
|
End;
|
||||||
|
//前[/tag]
|
||||||
|
tagInd := length(tagArr) - i + tmp['tail-begin-paragraph'] - 1;
|
||||||
|
if tmp['tail-begin-pos'] > 1 then Begin
|
||||||
|
nNode := run._duplicate_r(tagArr[tagInd]['rNode']);
|
||||||
|
run._adjust_r(tagArr[tagInd]['rNode'], 0, tmp['tail-begin-wz'] - 1);
|
||||||
|
tagArr[tagInd]['pNode'].DeleteChild(nNode);
|
||||||
|
tmp['tag-end'] := tagInd;
|
||||||
|
End
|
||||||
|
else if tmp['tail-begin-pos'] = 1 then Begin
|
||||||
|
tmp['tag-end'] := tagInd - 1;
|
||||||
|
End;
|
||||||
|
|
||||||
|
//[tag]后
|
||||||
|
firstNode := tagArr[0]['rNode'];
|
||||||
|
tagInd := length(tagArr) - i + tmp['head-end-paragraph'] - 1;
|
||||||
|
if tmp['head-end-pos'] < tmp['head-end-txtlen'] then Begin
|
||||||
|
oldNode := tagArr[tagInd]['rNode'];
|
||||||
|
tagArr[tagInd]['rNode'] := run._duplicate_r(oldNode);
|
||||||
|
run._adjust_r(tagArr[tagInd]['rNode'], tmp['head-end-wz'] - 1, tmp['head-end-txtlen']);
|
||||||
|
tmp['tag-beg'] := tagInd;
|
||||||
|
if tmp['head-begin-paragraph'] <> tmp['head-end-paragraph'] then
|
||||||
|
tagArr[tagInd]['pNode'].DeleteChild(oldNode);
|
||||||
|
End
|
||||||
|
else if tmp['head-end-pos'] = tmp['head-end-txtlen'] and tagInd then Begin
|
||||||
|
tmp['tag-beg'] := tagInd + 1;
|
||||||
|
End;
|
||||||
|
//前[tag]
|
||||||
|
if tmp['head-begin-pos'] > 1 then Begin
|
||||||
|
run._adjust_r(firstNode, 0, tmp['head-begin-wz'] - 1);
|
||||||
|
if firstNode = tagArr[0]['rNode'] then
|
||||||
|
tagArr[0]['rNode'] := nil;
|
||||||
|
End
|
||||||
|
else if tagInd=0 and tmp['tag-beg']=0 then
|
||||||
|
tagArr[0]['pNode'].DeleteChild(firstNode);
|
||||||
|
|
||||||
|
//执行TAG逻辑
|
||||||
|
r := array();
|
||||||
|
for nI := 0 to length(tagArr)-1 do Begin
|
||||||
|
if not ifObj(tagArr[nI]['rNode']) then continue;
|
||||||
|
if nI >= tmp['tag-beg'] and nI <= tmp['tag-end'] then
|
||||||
|
r[length(r)] := tagArr[nI];//标签中间文字内容
|
||||||
|
else Begin //删除标签
|
||||||
|
tagArr[nI]['pNode'].DeleteChild(tagArr[nI]['rNode']);
|
||||||
|
node := tagArr[nI]['pNode'].FirstChildElement('w:r');
|
||||||
|
if not ifObj(node) then Begin
|
||||||
|
tagArr[nI]['pNode'].Parent().DeleteChild(tagArr[nI]['pNode']);
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
tagObj.Init(tagName, tagAttribute, r);
|
||||||
|
tagObj.Apply();
|
||||||
|
tslTagCount++;
|
||||||
|
|
||||||
|
tagStatus := '';
|
||||||
|
tagArr := array();
|
||||||
|
break;
|
||||||
|
End
|
||||||
|
else if length(tagStr) < length(tagTail) and lowercase(c) = lowercase(tagTail[ length(tagStr) + 1 ]) then Begin
|
||||||
|
tagStr += tagTail[ length(tagStr) + 1 ];
|
||||||
|
if tagStr = '[' then Begin
|
||||||
|
tmp['tail-begin-paragraph'] := i;
|
||||||
|
tmp['tail-begin-pos'] := k;
|
||||||
|
tmp['tail-begin-wz'] := wz;
|
||||||
|
tmp['tail-begin-txtlen'] := txtLen;
|
||||||
|
End;
|
||||||
|
End
|
||||||
|
else //继续寻找TAG结束标志
|
||||||
|
tagStr := '';
|
||||||
|
End;
|
||||||
|
if Ord(c) > 127 then Begin
|
||||||
|
k ++;
|
||||||
|
End
|
||||||
|
k ++;
|
||||||
|
wz ++;
|
||||||
|
End;
|
||||||
|
if length(tagArr) then Begin
|
||||||
|
if i and i < length(tArr) and tArr[i]['pIndex'] <> tArr[i+1]['pIndex'] then Begin
|
||||||
|
endPos ++;
|
||||||
|
End;
|
||||||
|
ind := length(tagArr) - 1;
|
||||||
|
if tagArr[ind]['pIndex'] <> tArr[i]['pIndex'] or tagArr[ind]['rIndex'] <> tArr[i]['rIndex'] then
|
||||||
|
tagArr[ind + 1] := tArr[i];
|
||||||
|
End;
|
||||||
|
i += iStep;
|
||||||
|
End;
|
||||||
|
return array(length(errArr), tslTagCount, errArr);
|
||||||
|
End;
|
||||||
|
|
||||||
Function GetHeadingListImpl(docx, posOpt, UpperHeadingLevel, LowerHeadingLevel, numIds, bHeadList);
|
Function GetHeadingListImpl(docx, posOpt, UpperHeadingLevel, LowerHeadingLevel, numIds, bHeadList);
|
||||||
Begin
|
Begin
|
||||||
r := array();
|
r := array();
|
||||||
|
|
@ -13625,6 +13855,7 @@ Type TDocumentBody = Class(DocObject)
|
||||||
else Begin
|
else Begin
|
||||||
raise 'Invalid input param.';
|
raise 'Invalid input param.';
|
||||||
End;
|
End;
|
||||||
|
TOfficeApi().Set('CurrentPosition', o.node_);
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Function findNode(posOpt, b);
|
Function findNode(posOpt, b);
|
||||||
|
|
@ -14131,25 +14362,28 @@ Type TTable = Class(DocObject, TTableImpl)
|
||||||
|
|
||||||
///设置表格数据
|
///设置表格数据
|
||||||
///data: table,数据表
|
///data: table,数据表
|
||||||
///[IncludeHeader: bool] 是否包括表头,默认FALSE
|
///[includeHeader: bool] 是否包括表头,默认FALSE
|
||||||
///[IncludeIndex: bool] 是否自动添加索引号,默认FALSE
|
///[includeIndex: bool] 是否自动添加索引号,默认FALSE
|
||||||
Function SetData(docx, data, IncludeHeader, IncludeIndex);
|
Function SetData(docx, data, includeHeader, includeIndex);
|
||||||
Begin
|
Begin
|
||||||
if not IsTable(data) then
|
if not IsTable(data) then
|
||||||
raise "Invalid Data.";
|
raise "Invalid Data.";
|
||||||
|
[rowcount,colcount] := mSize(data);//一维数组
|
||||||
|
if colcount = 0 then
|
||||||
|
data := array(data);
|
||||||
fields := FieldNames(data);
|
fields := FieldNames(data);
|
||||||
if IsTable(fields) then Begin
|
if IsTable(fields) then Begin
|
||||||
r := nils(length(data),length(fields));
|
r := nils(length(data),length(fields));
|
||||||
r[:,:] := data;
|
r[:,:] := data;
|
||||||
data := r;
|
data := r;
|
||||||
End;
|
End;
|
||||||
if IncludeIndex then Begin
|
if includeIndex then Begin
|
||||||
n := length(data)-1;
|
n := length(data)-1;
|
||||||
r := array(0->n);
|
r := array(0->n);
|
||||||
data := `r | data;
|
data := `r | data;
|
||||||
End;
|
End;
|
||||||
if IncludeHeader and IsTable(fields) then Begin
|
if includeHeader and IsTable(fields) then Begin
|
||||||
if IncludeIndex then
|
if includeIndex then
|
||||||
fields := array("Index") union fields;
|
fields := array("Index") union fields;
|
||||||
data := array(fields) union data;
|
data := array(fields) union data;
|
||||||
End;
|
End;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Version 1.3.0
|
// Version 1.3.2
|
||||||
|
|
||||||
Type TSDocxFile = Class
|
Type TSDocxFile = Class
|
||||||
///Version: V1.0 2022-09-20
|
///Version: V1.0 2022-09-20
|
||||||
|
|
@ -271,6 +271,8 @@ Type TSDocxFile = Class
|
||||||
p := AddParagraph(p, getPosNode(posOpt), nil);
|
p := AddParagraph(p, getPosNode(posOpt), nil);
|
||||||
chart.pNode := p.node_;
|
chart.pNode := p.node_;
|
||||||
p.Node().InsertEndChild(o.GetInnerXml());
|
p.Node().InsertEndChild(o.GetInnerXml());
|
||||||
|
TOfficeApi().Set('CurrentShape', p.node_);
|
||||||
|
chart.chartFileName := 'word/charts/chart' $ o.ChartId_ $ '.xml';
|
||||||
return chart;
|
return chart;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
|
@ -292,6 +294,74 @@ Type TSDocxFile = Class
|
||||||
return r;
|
return r;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
///从Excel中Copy指定的chart图到文档中指定位置
|
||||||
|
///excelFileName:string xlsx文件名
|
||||||
|
///excelSheetName:string sheetname
|
||||||
|
///chartName:string or integer,chart图名称或当前sheet中chart图索引号
|
||||||
|
///Width:chart图宽度,单位cm
|
||||||
|
///Height:chart图高度,单位cm
|
||||||
|
///posOpt: 段落位置,0 在DOCX文件开头;-1 文件尾;N 在第N段之后;XmlNode节点对象或DocObject对象 在posOpt之后新添加图片
|
||||||
|
///返回TChart对象
|
||||||
|
Function CopyExcelChart(excelFileName, excelSheetName, chartName, Width, Height, posOpt);
|
||||||
|
Begin
|
||||||
|
excel := new TSExcelFile();
|
||||||
|
[err, msg] := excel.OpenFile('', excelFileName);
|
||||||
|
if err then return nil;
|
||||||
|
[err, charts] := excel.GetCharts(excelSheetName);
|
||||||
|
if err or length(charts)=0 then return nil;
|
||||||
|
drawingObj := excel.WorkBook().GetXmlFileObj(charts[0].drawingFileName);
|
||||||
|
if not ifObj(drawingObj) then return nil;
|
||||||
|
node := drawingObj.FirstChildElement('xdr:wsDr').FirstChildElement('xdr:twoCellAnchor');
|
||||||
|
ind := 0;
|
||||||
|
chartRid := '';
|
||||||
|
while ifObj(node) do Begin
|
||||||
|
findChart := false;
|
||||||
|
cNvPr := class(TSXml).GetNode(node, 'xdr:GraphicFrame/xdr:nvGraphicFramePr/xdr:cNvPr');
|
||||||
|
name := ifObj(cNvPr) ? cNvPr.GetAttribute('name') : '';
|
||||||
|
if ifstring(chartName) then Begin
|
||||||
|
if name = chartName then
|
||||||
|
find := true;
|
||||||
|
End
|
||||||
|
else if ifInt(chartName) and ind = chartName then
|
||||||
|
find := true;
|
||||||
|
if find then Begin
|
||||||
|
chartNode := class(TSXml).GetNode(node, 'xdr:GraphicFrame/a:graphic/a:graphicData/c:chart');
|
||||||
|
if not ifObj(chartNode) then return nil;
|
||||||
|
chartRid := chartNode.GetAttribute('r:id');
|
||||||
|
break;
|
||||||
|
End;
|
||||||
|
ind ++;
|
||||||
|
node := node.NextElement();
|
||||||
|
End;
|
||||||
|
for i:=0 to length(charts)-1 do Begin
|
||||||
|
if charts[i].Rid = chartRid then Begin
|
||||||
|
chart := TOfficeObj('TChart');
|
||||||
|
chart.Width := Width;
|
||||||
|
chart.Height := Height;
|
||||||
|
chart.Name := name;
|
||||||
|
chart.Type := 'line';
|
||||||
|
chart.ShowBubbleSize := false;
|
||||||
|
chart.ShowPercent := false;
|
||||||
|
chart.DataTable := false;
|
||||||
|
chart.AddSeries('test', array('line1'), array(1,2));
|
||||||
|
chart := AddChart(chart, getPosNode(posOpt));
|
||||||
|
xmlObj := Zip().Get(chart.chartFileName);
|
||||||
|
xmlObj.Data := charts[i].xmlObj.Data;
|
||||||
|
return chart;
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
return nil;
|
||||||
|
End;
|
||||||
|
|
||||||
|
///遍历文档中所有[TSTAG][/TSTAG]标签,针对每一个TAG执行tagObj.Apply()
|
||||||
|
///tagName:string 标签名称
|
||||||
|
///tagObj:TAG对象方法
|
||||||
|
///返回:[err,tslTagCount,errArr]: err 执行错误TAG次数,tslTagCount TAG总数,errArr 错误信息(array(('code':'代码', 'err':'错误信息')))
|
||||||
|
Function ExecTsTag(tagName, tagObj);
|
||||||
|
Begin
|
||||||
|
return Body().ExecTsTag(self, tagName, tagObj);
|
||||||
|
End;
|
||||||
|
|
||||||
///文档中全部的批注信息
|
///文档中全部的批注信息
|
||||||
///返回:DocComments对象
|
///返回:DocComments对象
|
||||||
Function Comments();
|
Function Comments();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Version 1.3.0
|
// Version 1.3.2
|
||||||
|
|
||||||
Type TSExcelFile = Class
|
Type TSExcelFile = Class
|
||||||
///Version: V1.0 2022-08-08
|
///Version: V1.0 2022-08-08
|
||||||
|
|
@ -349,10 +349,12 @@ Type TSExcelFile = Class
|
||||||
///sheet: string,工作表名称
|
///sheet: string,工作表名称
|
||||||
///topLeft: string,左上角坐标,如: "A4"
|
///topLeft: string,左上角坐标,如: "A4"
|
||||||
///bottomRight: string,右下角坐标,如: "B8",为空获取从topLeft开始的整张表
|
///bottomRight: string,右下角坐标,如: "B8",为空获取从topLeft开始的整张表
|
||||||
|
///[IncludeHeader: bool] 是否包括表头,默认FALSE
|
||||||
|
///[IncludeIndex: bool] 是否包括索引号,默认FALSE
|
||||||
///返回: table
|
///返回: table
|
||||||
Function GetTable(sheet, topLeft, bottomRight);
|
Function GetTable(sheet, topLeft, bottomRight, includeHeader, includeIndex, forceSingle);
|
||||||
Begin
|
Begin
|
||||||
return workbook_.GetTable(class(TSXml).CurCodePageToUtf8(sheet), topLeft, bottomRight);
|
return workbook_.GetTable(class(TSXml).CurCodePageToUtf8(sheet), topLeft, bottomRight, includeHeader, includeIndex, forceSingle);
|
||||||
End;
|
End;
|
||||||
|
|
||||||
///插入列,在指定列前插入空白列
|
///插入列,在指定列前插入空白列
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,11 @@ Type TOffice = Class
|
||||||
hash_['Paragraph-Node-' + name] := hash_['CurrentParagraph'];
|
hash_['Paragraph-Node-' + name] := hash_['CurrentParagraph'];
|
||||||
End;
|
End;
|
||||||
|
|
||||||
|
Function GetCurrentPosition()
|
||||||
|
Begin
|
||||||
|
return hash_['CurrentPosition'];
|
||||||
|
End;
|
||||||
|
|
||||||
///获取当前TSL代码段所在段落
|
///获取当前TSL代码段所在段落
|
||||||
///返回:TParagraph对象
|
///返回:TParagraph对象
|
||||||
Function GetCurrentParagraph();
|
Function GetCurrentParagraph();
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ Type TDocxChart = Class(TSChart)
|
||||||
chartId_ := 1 + vselect countof( ['FileName'] ) from docx.Zip().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;
|
||||||
|
chartFileName_ := chartFile;
|
||||||
docx.Zip().Add(chartFile, GetDefaultXml());
|
docx.Zip().Add(chartFile, GetDefaultXml());
|
||||||
xmlObj_ := docx.Zip().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
|
||||||
|
|
@ -29,16 +30,16 @@ Type TDocxChart = Class(TSChart)
|
||||||
Function GetInnerXml();
|
Function GetInnerXml();
|
||||||
Begin
|
Begin
|
||||||
ETU := 360045;//1cm单位
|
ETU := 360045;//1cm单位
|
||||||
return fmt('<w:r>
|
return format('<w:r>
|
||||||
<w:drawing>
|
<w:drawing>
|
||||||
<wp:inline>
|
<wp:inline>
|
||||||
<wp:extent cx="{}" cy="{}"/>
|
<wp:extent cx="%d" cy="%d"/>
|
||||||
<wp:effectExtent l="0" t="0" r="19050" b="19050"/>
|
<wp:effectExtent l="0" t="0" r="19050" b="19050"/>
|
||||||
<wp:docPr id="{}" name="{}"/>
|
<wp:docPr id="%d" name="%s"/>
|
||||||
<wp:cNvGraphicFramePr />
|
<wp:cNvGraphicFramePr />
|
||||||
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
|
<a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
|
||||||
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/chart">
|
<a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/chart">
|
||||||
<c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="rId{}"/>
|
<c:chart xmlns:c="http://schemas.openxmlformats.org/drawingml/2006/chart" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" r:id="rId%d"/>
|
||||||
</a:graphicData>
|
</a:graphicData>
|
||||||
</a:graphic>
|
</a:graphic>
|
||||||
</wp:inline>
|
</wp:inline>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
Type TSTag = Class
|
||||||
|
///缺省构造函数
|
||||||
|
Function Create(); overload;
|
||||||
|
Begin
|
||||||
|
End;
|
||||||
|
|
||||||
|
Function Init(tagName, attribute, r);
|
||||||
|
Begin
|
||||||
|
tagName_ := tagName;
|
||||||
|
attribute_ := attribute;
|
||||||
|
runArr_ := r;
|
||||||
|
range_ := nil;
|
||||||
|
map_ := nil;
|
||||||
|
End;
|
||||||
|
|
||||||
|
Property Range read readRange;
|
||||||
|
Function readRange();
|
||||||
|
Begin
|
||||||
|
if ifNil(range_) then Begin
|
||||||
|
range_ := TOfficeObj('TRange');
|
||||||
|
range_.Init(runArr_);
|
||||||
|
End;
|
||||||
|
return range_;
|
||||||
|
End;
|
||||||
|
|
||||||
|
///获取TAG中属性 [font size=12]...[/font]
|
||||||
|
/// tag.GetAttribute('size');
|
||||||
|
///返回:string
|
||||||
|
Function GetAttribute(key);
|
||||||
|
Begin
|
||||||
|
if not ifArray(map_) then Begin
|
||||||
|
map_ := array();
|
||||||
|
//println('attribute={}',attribute_);
|
||||||
|
arr := Str2Array(attribute_, ' ');
|
||||||
|
for i := 0 to length(arr)-1 do Begin
|
||||||
|
kv := Str2Array(arr[i], '=');
|
||||||
|
if length(kv)=2 then
|
||||||
|
map_[kv[0]] := kv[1];
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
return map_[key];
|
||||||
|
End;
|
||||||
|
|
||||||
|
Function Apply(); virtual;
|
||||||
|
Begin
|
||||||
|
case tagName_ of
|
||||||
|
'add':
|
||||||
|
_add();
|
||||||
|
'del':
|
||||||
|
_del();
|
||||||
|
End;
|
||||||
|
End;
|
||||||
|
|
||||||
|
Function _add();
|
||||||
|
Begin
|
||||||
|
Range.Font.Size := 40;
|
||||||
|
Range.Font.Color := 'FF0000';
|
||||||
|
Range.Font.Bold := true;
|
||||||
|
Range.Apply();
|
||||||
|
End;
|
||||||
|
|
||||||
|
Function _del();
|
||||||
|
Begin
|
||||||
|
Range.Clear();
|
||||||
|
End;
|
||||||
|
|
||||||
|
tagName_:string;
|
||||||
|
attribute_:string;
|
||||||
|
runArr_;
|
||||||
|
range_;
|
||||||
|
map_;
|
||||||
|
End;
|
||||||
|
|
@ -124,7 +124,7 @@ xmlns:v="urn:schemas-microsoft-com:vml">
|
||||||
if ifObj(node) then Begin
|
if ifObj(node) then Begin
|
||||||
[err, col, row] := excel_.CellNameToCoordinates(cell);
|
[err, col, row] := excel_.CellNameToCoordinates(cell);
|
||||||
clientData := TOfficeObj('TClientData');
|
clientData := TOfficeObj('TClientData');
|
||||||
clientData.Anchor := fmt('{},23,{},0,{},{},{},5',col, row, 1+col+lineCount, colCount+col-1, 1+row+lineCount);
|
clientData.Anchor := format('%d,23,%d,0,%d,%d,%d,5',col, row, 1+col+lineCount, colCount+col-1, 1+row+lineCount);
|
||||||
clientData.Row := row - 1;
|
clientData.Row := row - 1;
|
||||||
ClientData.Column := col - 1;
|
ClientData.Column := col - 1;
|
||||||
node.UnMarshal(clientData.Marshal());
|
node.UnMarshal(clientData.Marshal());
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ private
|
||||||
name := "列" $ col_index++;
|
name := "列" $ col_index++;
|
||||||
excel_.WorkBook().SetCellValue(sheetName_, cell, name);
|
excel_.WorkBook().SetCellValue(sheetName_, cell, name);
|
||||||
end
|
end
|
||||||
table_str += fmt('<tableColumn id="{}" name="{}" />', id++, name);
|
table_str += format('<tableColumn id="%d" name="%s" />', id, name);
|
||||||
end
|
end
|
||||||
table_str += "</tableColumns>";
|
table_str += "</tableColumns>";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,14 +138,30 @@ Type xlsxWorkBook = Class
|
||||||
return class(ErrorMessage).Fail();
|
return class(ErrorMessage).Fail();
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Function GetTable(sheet, topLeft, bottomRight);
|
Function GetTable(sheet, topLeft, bottomRight, includeHeader, includeIndex, forceSingle);
|
||||||
Begin
|
Begin
|
||||||
o := GetSheetObj(sheet);
|
o := GetSheetObj(sheet);
|
||||||
if ifObj(o) then return o.Import(topLeft, bottomRight);
|
if ifObj(o) then
|
||||||
|
begin
|
||||||
|
data := o.Import(topLeft, bottomRight, includeHeader, includeIndex, forceSingle);
|
||||||
|
if not TOfficeApi().IsUtf8() then
|
||||||
|
begin
|
||||||
|
fields := fieldnames(data);
|
||||||
|
if ifarray(fields) and length(fields) then
|
||||||
|
begin
|
||||||
|
map := array();
|
||||||
|
for i:=0 to length(fields)-1 do
|
||||||
|
map[fields[i]] := class(TSXml).Utf8ToCurCodePage(fields[i]);
|
||||||
|
reindex(data, nil, map);
|
||||||
|
end
|
||||||
|
data::begin
|
||||||
|
if ifstring(mcell) then mcell := class(TSXml).Utf8ToCurCodePage(mcell);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return data;
|
||||||
|
end
|
||||||
End;
|
End;
|
||||||
|
|
||||||
///创建新sheet
|
|
||||||
///sheet: string,工作表名称
|
|
||||||
Function NewSheet(sheet);overload;
|
Function NewSheet(sheet);overload;
|
||||||
Begin
|
Begin
|
||||||
lname := LowerCase(sheet);
|
lname := LowerCase(sheet);
|
||||||
|
|
@ -678,6 +694,7 @@ Type xlsxWorkBook = Class
|
||||||
chartFile := ReplaceStr(target, '..', 'xl');
|
chartFile := ReplaceStr(target, '..', 'xl');
|
||||||
chart := TOfficeObj('TChart');
|
chart := TOfficeObj('TChart');
|
||||||
chart.Rid := node.GetAttribute('Id'); //rid
|
chart.Rid := node.GetAttribute('Id'); //rid
|
||||||
|
chart.drawingFileName := drawingFile;
|
||||||
setChartInfo(chartFile, chart);
|
setChartInfo(chartFile, chart);
|
||||||
charts[i] := chart;
|
charts[i] := chart;
|
||||||
i++;
|
i++;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue