add `TSTag` and wordtemplate
This commit is contained in:
parent
c536c4d531
commit
10ef45f1a0
|
|
@ -1353,6 +1353,7 @@ type TChartImpl=class(NodeInfo)
|
|||
,("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":"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;
|
||||
End;
|
||||
|
||||
|
|
@ -1395,6 +1396,7 @@ type TChartImpl=class(NodeInfo)
|
|||
Excel;
|
||||
chartFileName;
|
||||
excelFileName;
|
||||
drawingFileName;
|
||||
End;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
|
@ -13492,6 +13494,235 @@ Type TDocumentBody = Class(DocObject)
|
|||
return array(length(errArr), tslFuncCount, errArr);
|
||||
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);
|
||||
End
|
||||
else if tmp['tail-begin-pos'] = 1 then Begin
|
||||
if _remove_run(tagArr[tagInd]['pNode'], tagArr[tagInd]['rNode']) then
|
||||
tagArr[tagInd]['pNode'] := nil;
|
||||
tagArr[tagInd]['rNode'] := nil;
|
||||
End;
|
||||
//删除[/TAG]尾部
|
||||
for delI := tagInd+1 to length(tagArr)-1 do Begin
|
||||
if _remove_run(tagArr[delI]['pNode'], tagArr[delI]['rNode']) then
|
||||
tagArr[delI]['pNode'] := nil;
|
||||
tagArr[delI]['rNode'] := nil;
|
||||
End;
|
||||
|
||||
//[tag]后
|
||||
firstNode := tagArr[0]['rNode'];
|
||||
tagInd := length(tagArr) - i + tmp['head-end-paragraph'] - 1;
|
||||
//println('===============================head-end-pos={},head-end-txtlen={}',tmp['head-end-pos'] , tmp['head-end-txtlen']);
|
||||
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']);
|
||||
End
|
||||
else if tmp['head-end-pos'] = tmp['head-end-txtlen'] and tagInd then Begin
|
||||
if _remove_run(tagArr[tagInd]['pNode'], tagArr[tagInd]['rNode']) then
|
||||
tagArr[tagInd]['pNode'] := nil;
|
||||
tagArr[tagInd]['rNode'] := nil;
|
||||
End;
|
||||
//前[tag]
|
||||
if tmp['head-begin-pos'] > 1 then Begin
|
||||
run._adjust_r(firstNode, 0, tmp['head-begin-wz'] - 1);
|
||||
if tmp['head-begin-paragraph'] <> tmp['head-end-paragraph'] then
|
||||
tagArr[0]['rNode'] := nil;
|
||||
End
|
||||
else if tmp['head-begin-pos'] = 1 then Begin
|
||||
if _remove_run(tagArr[0]['pNode'], firstNode) then
|
||||
tagArr[0]['pNode'] := nil;
|
||||
if tmp['head-begin-paragraph'] <> tmp['head-end-paragraph'] then
|
||||
tagArr[0]['rNode'] := nil;
|
||||
End;
|
||||
for delI := 1 to tagInd-1 do Begin
|
||||
if _remove_run(tagArr[delI]['pNode'], tagArr[delI]['rNode']) then
|
||||
tagArr[delI]['pNode'] := nil;
|
||||
tagArr[delI]['rNode'] := nil;
|
||||
End;
|
||||
|
||||
//执行TAG逻辑
|
||||
r := array();
|
||||
for nI := 0 to length(tagArr)-1 do Begin
|
||||
if ifObj(tagArr[nI]['rNode']) then
|
||||
r[length(r)] := tagArr[nI];
|
||||
End;
|
||||
tagObj.Init(tagName, attribute, 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);
|
||||
Begin
|
||||
r := array();
|
||||
|
|
@ -13679,6 +13910,17 @@ Type TDocumentBody = Class(DocObject)
|
|||
End;
|
||||
End;
|
||||
|
||||
Function _remove_run(pNode, rNode);
|
||||
Begin
|
||||
pNode.DeleteChild(rNode);
|
||||
node := pNode.FirstChildElement('w:r');
|
||||
if not ifObj(node) then Begin
|
||||
pNode.Parent().DeleteChild(pNode);
|
||||
return true;
|
||||
End;
|
||||
return false;
|
||||
End;
|
||||
|
||||
zipfile_;
|
||||
lastParagraph_;
|
||||
document_;
|
||||
|
|
|
|||
|
|
@ -272,6 +272,7 @@ Type TSDocxFile = Class
|
|||
chart.pNode := p.node_;
|
||||
p.Node().InsertEndChild(o.GetInnerXml());
|
||||
TOfficeApi().Set('CurrentShape', p.node_);
|
||||
chart.chartFileName := 'word/charts/chart' $ o.ChartId_ $ '.xml';
|
||||
return chart;
|
||||
End;
|
||||
|
||||
|
|
@ -293,6 +294,74 @@ Type TSDocxFile = Class
|
|||
return r;
|
||||
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对象
|
||||
Function Comments();
|
||||
|
|
|
|||
|
|
@ -349,10 +349,12 @@ Type TSExcelFile = Class
|
|||
///sheet: string,工作表名称
|
||||
///topLeft: string,左上角坐标,如: "A4"
|
||||
///bottomRight: string,右下角坐标,如: "B8",为空获取从topLeft开始的整张表
|
||||
///[IncludeHeader: bool] 是否包括表头,默认FALSE
|
||||
///[IncludeIndex: bool] 是否包括索引号,默认FALSE
|
||||
///返回: table
|
||||
Function GetTable(sheet, topLeft, bottomRight);
|
||||
Function GetTable(sheet, topLeft, bottomRight, includeHeader, includeIndex, forceSingle);
|
||||
Begin
|
||||
return workbook_.GetTable(class(TSXml).CurCodePageToUtf8(sheet), topLeft, bottomRight);
|
||||
return workbook_.GetTable(class(TSXml).CurCodePageToUtf8(sheet), topLeft, bottomRight, includeHeader, includeIndex, forceSingle);
|
||||
End;
|
||||
|
||||
///插入列,在指定列前插入空白列
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ Type TDocxChart = Class(TSChart)
|
|||
chartId_ := 1 + vselect countof( ['FileName'] ) from docx.Zip().Files() where AnsiStartsText('word/charts/chart', ['FileName']) end;
|
||||
targetFileName := 'charts/chart' $ chartId_ $ '.xml';
|
||||
chartFile := 'word/' + targetFileName;
|
||||
chartFileName_ := chartFile;
|
||||
docx.Zip().Add(chartFile, GetDefaultXml());
|
||||
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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
Type TSTag = Class
|
||||
///缺省构造函数
|
||||
Function Create(); overload;
|
||||
Begin
|
||||
End;
|
||||
|
||||
Function Init(tagName, attribute, r);
|
||||
Begin
|
||||
tagName_ := tagName;
|
||||
attribute_ := attribute;
|
||||
runArr_ := r;
|
||||
End;
|
||||
|
||||
Function Apply(); virtual;
|
||||
Begin
|
||||
case tagName_ of
|
||||
'add':
|
||||
_add();
|
||||
'del':
|
||||
_del();
|
||||
End;
|
||||
End;
|
||||
|
||||
Function _add();
|
||||
Begin
|
||||
for i:=0 to length(runArr_)-1 do Begin
|
||||
run := TOfficeObj('TRun');
|
||||
run.Init(runArr_[i]['rNode']);
|
||||
run.Font.Size := 40;
|
||||
run.Font.Color := 'FF0000';
|
||||
run.Font.Bold := true;
|
||||
run.Apply();
|
||||
End;
|
||||
End;
|
||||
|
||||
Function _del();
|
||||
Begin
|
||||
for i:=0 to length(runArr_)-1 do Begin
|
||||
runArr_[i]['pNode'].DeleteChild(runArr_[i]['rNode']);
|
||||
child := runArr_[i]['pNode'].FirstChildElement('w:r');
|
||||
if not ifObj(child) then
|
||||
runArr_[i]['pNode'].Parent().DeleteChild(runArr_[i]['pNode']);
|
||||
End;
|
||||
End;
|
||||
|
||||
tagName_:string;
|
||||
attribute_:string;
|
||||
runArr_;
|
||||
End;
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
Function _ExcelChartCopyPic(excelFileName, excelSheetName, picType);
|
||||
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;
|
||||
|
|
@ -138,7 +138,7 @@ Type xlsxWorkBook = Class
|
|||
return class(ErrorMessage).Fail();
|
||||
End;
|
||||
|
||||
Function GetTable(sheet, topLeft, bottomRight);
|
||||
Function GetTable(sheet, topLeft, bottomRight, includeHeader, includeIndex, forceSingle);
|
||||
Begin
|
||||
o := GetSheetObj(sheet);
|
||||
if ifObj(o) then
|
||||
|
|
@ -162,8 +162,6 @@ Type xlsxWorkBook = Class
|
|||
end
|
||||
End;
|
||||
|
||||
///创建新sheet
|
||||
///sheet: string,工作表名称
|
||||
Function NewSheet(sheet);overload;
|
||||
Begin
|
||||
lname := LowerCase(sheet);
|
||||
|
|
@ -696,6 +694,7 @@ Type xlsxWorkBook = Class
|
|||
chartFile := ReplaceStr(target, '..', 'xl');
|
||||
chart := TOfficeObj('TChart');
|
||||
chart.Rid := node.GetAttribute('Id'); //rid
|
||||
chart.drawingFileName := drawingFile;
|
||||
setChartInfo(chartFile, chart);
|
||||
charts[i] := chart;
|
||||
i++;
|
||||
|
|
@ -1148,6 +1147,14 @@ Type xlsxWorkBook = Class
|
|||
|
||||
Function ProtectSheet(sheet, protect);
|
||||
Begin
|
||||
if protect.AlgorithmName and protect.Password then
|
||||
begin
|
||||
protect.SaltValue := nil;//protect.Password;
|
||||
protect.HashValue := nil;//GetMsgDigest(protect.SaltValue, 6);
|
||||
protect.SpinCount := nil;
|
||||
protect.Password := nil;
|
||||
protect.AlgorithmName := nil;
|
||||
end
|
||||
sheet_obj := GetSheetXmlfile(sheet);
|
||||
work_node := sheet_obj.FirstChildElement('worksheet');
|
||||
sheet_protection_node := work_node.FirstChildElement('sheetProtection');
|
||||
|
|
|
|||
Loading…
Reference in New Issue