init word_templat

This commit is contained in:
csh
2023-05-16 16:49:34 +08:00
parent 823aa12a98
commit 4dc02530ba
30 changed files with 353 additions and 83 deletions
+83 -83
View File
@@ -9933,7 +9933,7 @@ type TProtect=class(NodeInfo)
Function GetAttrs(); override;
Begin
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;
Function GetChildren(); override;
@@ -9943,6 +9943,11 @@ type TProtect=class(NodeInfo)
End;
//Attributes
Password;
AlgorithmName;
HashValue;
SaltValue;
SpinCount;
Sheet;
EditObjects;
EditScenarios;
@@ -11323,20 +11328,22 @@ Type TPicture = Class(DocObject, TPictureImpl)
ETU := 360045;//1cm单位
maxX := 17.0;//水平方向17cm
maxY := 23.0;//垂直方向23cm
imageW := image.Width() / 28.346 * ETU;
imageH := image.Height() / 28.346 * ETU;
if Width <= 0 and Height <= 0 then Begin //图像缺省大小
widthVal := image.Width();
heightVal := image.Height();
widthVal := imageW;
heightVal := imageH;
End
else Begin //用户设置了图片尺寸
widthVal := ETU * Width;
heightVal := ETU * Height;
if Width <= 0 and image.Height() and image.Width() then Begin //按照图片比例自动缩放
scaling_factor := image.Width() / image.Height();
if Width <= 0 and imageH and imageW then Begin //按照图片比例自动缩放
scaling_factor := imageW / imageH;
widthVal := round(heightVal * scaling_factor);
End;
if Height <= 0 and image.Height() and image.Width() then Begin //按照图片比例自动缩放
scaling_factor := image.Width() / image.Height();
if Height <= 0 and imageH and imageW then Begin //按照图片比例自动缩放
scaling_factor := imageW / imageH;
heightVal := round(widthVal / scaling_factor);
End;
End;
@@ -11361,7 +11368,7 @@ Type TPicture = Class(DocObject, TPictureImpl)
heightVal *= ratio;
widthVal *= ratio;
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));
End;
@@ -12946,6 +12953,7 @@ Type TDocumentBody = Class(DocObject)
Function InsertTable(tbl, posOpt);
Begin
addPart(posOpt, tbl);
TOfficeApi().Set('CurrentTable', tbl.node_);
tblBorders := class(TSXml).GetNode(tbl.node_, 'w:tblPr/w:tblBorders');
tblCellMar := class(TSXml).GetNode(tbl.node_, 'w:tblPr/w:tblCellMar');
if ifObj(tblBorders) or ifObj(tblCellMar) then Begin
@@ -13107,6 +13115,7 @@ Type TDocumentBody = Class(DocObject)
p := new TPicture(picture.node_);
_set_lastParagraph_(posOpt, picture.node_);
TOfficeApi().Set('CurrentShape', picture.node_);
return p;
End;
@@ -13268,8 +13277,9 @@ Type TDocumentBody = Class(DocObject)
begParagraphIndex := -1;
begPos := 0;
begTxtLen := 0;
for i:=0 to length(tArr)-1 do Begin
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();
@@ -13342,7 +13352,8 @@ Type TDocumentBody = Class(DocObject)
flag := '[TSL]';
'[TSL][/TSL':
if c = ']' then Begin
curParagraphNode := tslArr[0]['pNode'];
tslBegParagraphNode := tslArr[0]['pNode'];
tslEndParagraphNode := tArr[i]['pNode'];
ind := length(tslArr) - 1;
if tslArr[ind]['pIndex'] <> tArr[i]['pIndex'] or tslArr[ind]['rIndex'] <> tArr[i]['rIndex'] then Begin
ind ++;
@@ -13359,7 +13370,7 @@ Type TDocumentBody = Class(DocObject)
oldNode := prevRun;
tArr[i]['rNode'] := run._duplicate_r(oldNode);
run._adjust_r(tArr[i]['rNode'], wz, txtLen);
i--;
iStep := 0;
End;
curRunNode := tslArr[0]['rNode'];
curRun := new TRun(curRunNode);
@@ -13382,84 +13393,68 @@ Type TDocumentBody = Class(DocObject)
code := leftstr(code, lengthW(code) - 5 - endPos);
CodePage := TOfficeApi().Get('CodePage');
TOfficeApi().Set('Docx', docx);
TOfficeApi().Set('CurrentParagraph', curParagraphNode);
TOfficeApi().Set('CurrentParagraph', tslBegParagraphNode);
TOfficeApi().Set('CurrentPosition', tslBegParagraphNode);
TOfficeApi().Set('CurrentRun', curRunNode);
TOfficeApi().Set('CodePage', 'gbk');
try
tslFuncCount ++;
println('run code=[{}]', code);
if code <> '' then
str := eval(&code);
eval(&code);
except
println('run code={},err={}', code, ExceptObject.ErrInfo);
errArr[ length(errArr) ] := array('code':code, 'err':ExceptObject.ErrInfo);
str := '';
End;
tNode := curRun.node_.FirstChildElement('w:t');
if not ifObj(tNode) then Begin //没有在外部插入文字
if not ifstring(str) or str = '' then Begin //删除w:r
curParagraphNode.DeleteChild(curRunNode);
hasrNode := curParagraphNode.FirstChildElement('w:r');
if not ifObj(hasrNode) then Begin//删除空段落
curParagraphNode.Parent().DeleteChild(curParagraphNode);
curParagraphNode := nil;
End;
End
else Begin
str := AnsiToUTF8(str);
lines := str2array(str, '\r\n');
lineCnt := length(lines);
if lineCnt = 1 then Begin //单行
curRun.SetText(str, true);
tslBegParagraphNode.DeleteChild(curRunNode);
//兼容WordTemplate函数,不删除空段落(TSL脚本段落)
//hasrNode := tslBegParagraphNode.FirstChildElement('w:r');
//if not ifObj(hasrNode) then Begin//删除空段落
// tslBegParagraphNode.Parent().DeleteChild(tslBegParagraphNode);
// tslBegParagraphNode := nil;
//End;
End;
//段落炸裂
curPosotion := TOfficeApi().Get('CurrentPosition');
if i+iStep < length(tArr) and tArr[i+iStep]['pNode'] = tslEndParagraphNode and tslBegParagraphNode <> curPosotion then Begin
data := tslEndParagraphNode.Marshal();
NewParagraphNode := tslEndParagraphNode.Parent().InsertAfterChild(curPosotion, data[0]);//复制段落
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
else Begin //多行
curRun.SetText(lines[0], true);
nextRun := curRun.node_.NextElement('w:r');
if ifObj(nextRun) then Begin //段落炸裂
curLine := 0;
prevRNode := curRunNode;
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;
else Begin
tArr[i+iStep+nI]['pNode'] := NewParagraphNode;
tArr[i+iStep+nI]['rNode'] := rNode;
tArr[i+iStep+nI]['rIndex'] := rIndex++;
nr := new TRun(tArr[i+iStep+nI]['rNode']);
nI ++;
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;
TOfficeApi().Set('CodePage', CodePage);
@@ -13467,7 +13462,7 @@ Type TDocumentBody = Class(DocObject)
flag := '';
code := nil;
tslArr := array();
continue;
break;
End
else
flag := '[TSL]';
@@ -13492,6 +13487,7 @@ Type TDocumentBody = Class(DocObject)
if tslArr[ind]['pIndex'] <> tArr[i]['pIndex'] or tslArr[ind]['rIndex'] <> tArr[i]['rIndex'] then
tslArr[ind + 1] := tArr[i];
End;
i += iStep;
End;
return array(length(errArr), tslFuncCount, errArr);
End;
@@ -13625,6 +13621,7 @@ Type TDocumentBody = Class(DocObject)
else Begin
raise 'Invalid input param.';
End;
TOfficeApi().Set('CurrentPosition', o.node_);
End;
Function findNode(posOpt, b);
@@ -14131,25 +14128,28 @@ Type TTable = Class(DocObject, TTableImpl)
///设置表格数据
///data: table,数据表
///[IncludeHeader: bool] 是否包括表头,默认FALSE
///[IncludeIndex: bool] 是否自动添加索引号,默认FALSE
Function SetData(docx, data, IncludeHeader, IncludeIndex);
///[includeHeader: bool] 是否包括表头,默认FALSE
///[includeIndex: bool] 是否自动添加索引号,默认FALSE
Function SetData(docx, data, includeHeader, includeIndex);
Begin
if not IsTable(data) then
raise "Invalid Data.";
[rowcount,colcount] := mSize(data);//一维数组
if colcount = 0 then
data := array(data);
fields := FieldNames(data);
if IsTable(fields) then Begin
r := nils(length(data),length(fields));
r[:,:] := data;
data := r;
End;
if IncludeIndex then Begin
if includeIndex then Begin
n := length(data)-1;
r := array(0->n);
data := `r | data;
End;
if IncludeHeader and IsTable(fields) then Begin
if IncludeIndex then
if includeHeader and IsTable(fields) then Begin
if includeIndex then
fields := array("Index") union fields;
data := array(fields) union data;
End;
+1
View File
@@ -271,6 +271,7 @@ Type TSDocxFile = Class
p := AddParagraph(p, getPosNode(posOpt), nil);
chart.pNode := p.node_;
p.Node().InsertEndChild(o.GetInnerXml());
TOfficeApi().Set('CurrentShape', p.node_);
return chart;
End;
+5
View File
@@ -73,6 +73,11 @@ Type TOffice = Class
hash_['Paragraph-Node-' + name] := hash_['CurrentParagraph'];
End;
Function GetCurrentPosition()
Begin
return hash_['CurrentPosition'];
End;
///获取当前TSL代码段所在段落
///返回:TParagraph对象
Function GetCurrentParagraph();
@@ -0,0 +1,3 @@
Function _ExcelChartCopyPic(excelFileName, excelSheetName, picType);
Begin
End;
@@ -0,0 +1,3 @@
Function _WordAddOleObjectFromFile(fileName, width, height);
Begin
End;
+5
View File
@@ -0,0 +1,5 @@
Function _WordBr();
Begin
TOfficeApi().GetDocument().AddLineBreak(TOfficeApi().Get('CurrentPosition'));
End;
@@ -0,0 +1,34 @@
Function _WordCopyFromExcel(excelFileName, excelSheetName, startRow, startCol, endRow, endCol);
Begin
excel := new TSExcelFile();
[err, msg] := excel.OpenFile('', excelFileName);
if err then return false;
total_row := excel.TotalRows(excelSheetName);
total_col := excel.TotalCols(excelSheetName);
if not total_row or not total_col then return false;
if ifnil(startRow) then
startRow := 1;
if ifnil(startCol) then
startCol := 1;
if ifnil(endRow) then
endRow := total_row;
if ifnil(endCol) then
endCol := total_col;
data := excel.GetTable(excelSheetName,
CoordinatesToCellName(startCol, startRow),
CoordinatesToCellName(endCol, endRow),
false,
false,
false);
if length(data) = 0 then return false;
//println('data={}',data);
docx := TOfficeApi().GetDocument();
tbl := docx.CreateTable(data, false, false);
tbl.Format.Borders.Top.Val := 'dashed';
tbl.Format.Borders.Left.Val := 'dashed';
tbl.Format.Borders.Bottom.Val := 'dashed';
tbl.Format.Borders.Right.Val := 'dashed';
tbl.Format.Borders.InsideH.Val := 'dashed';
tbl.Format.Borders.InsideV.Val := 'dashed';
tbl := docx.InsertTable(tbl, TOfficeApi().GetCurrentPosition());
End;
@@ -0,0 +1,3 @@
Function _WordCopyPicFormatExcel(excelFileName, excelSheetName, startRow, startCol, endRow, endCol, picType);
Begin
End;
@@ -0,0 +1,4 @@
Function _WordGetCurrentDocument();
Begin
return TOfficeApi().GetDocument();
End;
@@ -0,0 +1,4 @@
Function _WordGetCurrentRange();
Begin
return TOfficeApi().GetCurrentPosition();
End;
+10
View File
@@ -0,0 +1,10 @@
Function _WordGetFont(prop, value);
Begin
crun := TOfficeApi().GetCurrentRun();
node := crun.Node().FirstChildElement('w:rPr');
rPr := TOfficeObj('TwrPr');
rPr.InitRootNode(node);
value := rPr.Value(prop);
if not ifnil(value) then return true;
return false;
End;
@@ -0,0 +1,4 @@
Function _WordGetLastRange();
Begin
return TOfficeApi().GetCurrentPosition();
End;
@@ -0,0 +1,16 @@
Function _WordGetLastShape();
Begin
node := TOfficeApi().Get('CurrentShape');
if not ifObj(node) then return nil;
uri := 'w:r/w:drawing/wp:inline/a:graphic/a:graphicData/c:chart';
cNode := class(TSXml).GetNode(node, uri);
if ifObj(cNode) then Begin
chart := TOfficeObj('TChart');
chart.Init(TOfficeApi().GetDocument(), node, cNode);
return chart;
End;
pic := TOfficeObj('TPicture');
pic.Init(node);
return pic;
End;
@@ -0,0 +1,4 @@
Function _WordGetLastTable();
Begin
return TOfficeApi().Get('LastTable');
End;
@@ -0,0 +1,12 @@
Function _WordGetLastTableCellProp(row, col, name, value);
Begin
table := TOfficeApi().Get('LastTable');
if ifnil(table) then return false;
table_cell := table.Cell(row, col);
ctr := _wordCompTable();
name_ := ctr[lowercase(name)];
if ifnil(name_) then name_ := name;
str := 'return table_cell.Format.' $ name_ $ '"' $ value $ '"';
value := eval(&str);
return true;
End;
@@ -0,0 +1,11 @@
Function _WordGetLastTableProp(name, value);
Begin
table := TOfficeApi().Get('LastTable');
if ifnil(table) then return false;
ctr := _wordCompTable();
name_ := ctr[lowercase(name)];
if ifnil(name_) then name_ := name;
str := 'return table.Format.' $ name_ $ '"' $ value $ '"';
value := eval(&str);
return true;
End;
@@ -0,0 +1,3 @@
Function _WordGetRangeProp(name, value);
Begin
End;
@@ -0,0 +1,11 @@
Function _WordLastTableMerge(row1, col1, row2, col2);
Begin
table := TOfficeApi().Get('LastTable');
if ifnil(table) then return false;
[err1, beg_cell] := CoordinatesToCellName(col1, row1);
[err2, end_cell] := CoordinatesToCellName(col2, row2);
if err1 or err2 then return false;
table.Merge(beg_cell, end_cell, false);
TOfficeApi().Set('LastTable', table);
return true;
End;
@@ -0,0 +1,3 @@
Function _WordLastTableSplit(row, col, rCnt, cCnt);
Begin
End;
@@ -0,0 +1,4 @@
Function _WordSetCurrnetRange(range);
Begin
TOfficeApi().Set('CurrentPosition', range);
End;
+8
View File
@@ -0,0 +1,8 @@
Function _WordSetFont(prop, value);
Begin
run := TOfficeApi().GetCurrentRun();
str := 'run.font.' $ prop $ ' := ' $ '"' $ value $ '"';
eval(&str);
run.Apply();
return true;
End;
@@ -0,0 +1,17 @@
Function _WordSetLastTableCellProp(row, col, name, value);
Begin
table := TOfficeApi().Get('LastTable');
if ifnil(table) then return false;
table_cell := table.Cell(row, col);
ctr := _wordCompTable();
name_ := ctr[lowercase(name)];
if ifnil(name_) then name_ := name;
str := 'table_cell.Format.' $ name_ $ ' := ';
if ifstring(value) then
str += '"' $ value $ '"';
else
str = str $ value;
eval(&str);
TOfficeApi().Set('LastTable', table);
return true;
End;
@@ -0,0 +1,18 @@
Function _WordSetLastTableProp(name, value);
Begin
table := TOfficeApi().Get('LastTable');
if ifnil(table) then return false;
ctr := _wordCompTable();
name_ := ctr[lowercase(name)];
if ifnil(name_) then name_ := name;
str := 'table.Format.' $ name_ $ ' := ';
if ifstring(value) then
str += '"' $ value $ '"';
else
str = str $ value;
println("str = {}", str);
eval(&str);
TOfficeApi().Set('LastTable', table);
return true;
End;
@@ -0,0 +1,5 @@
Function _WordSetRangeProp(name, value);
Begin
cur := TOfficeApi().GetCurrentPosition();
if ifnil(cur) then return nil;
End;
+10
View File
@@ -0,0 +1,10 @@
Function _WordTemplate(alias, fileName);
Begin
docx := new TSDocxFile();
[err, msg] := docx.OpenFile(alias, fileName);
if err then return false;
docx.ExecInnerTSL();
[err, msg] := docx.Save();
if err then return false;
return true;
End;
+17
View File
@@ -0,0 +1,17 @@
Function _WordWrite();
Begin
docx := TOfficeApi().GetDocument();
curParagraph := TOfficeApi().GetCurrentParagraph();
curRun := TOfficeApi().GetCurrentRun();
for i:=1 to PARAMCOUNT do Begin
argv := params[i];
if ifstring( argv ) then
curRun.AddText( argv );
else if ifnumber(argv) then
curRun.AddText('' $ argv);
else if ifarray(argv) then Begin
tbl := docx.CreateTable(argv, false, false);
tbl := docx.InsertTable(tbl, TOfficeApi().GetCurrentPosition());
End
End
End;
@@ -0,0 +1,11 @@
Function _WordWritePicFromFile(fileName);
Begin
file_size := fileSize('', fileName);
flag := readfile(rwbinary(), '', fileName, 0, file_size, data);
if not flag then return false;
picture := TOfficeObj('TPicture');
picture.Image := data;
docx := TOfficeApi().GetDocument();
docx.AddPicture(picture, TOfficeApi().GetCurrentPosition());
return true;
End;
@@ -0,0 +1,8 @@
Function _WordWriteTable(table, writeIntIndex, writeIntTitle, incIntIndex);
Begin
docx := TOfficeApi().GetDocument();
tbl := docx.CreateTable(table, true, writeIntIndex);
table := docx.InsertTable(tbl, TOfficeApi().GetCurrentPosition());
TOfficeApi().Set('LastTable', table);
return true;
End;
+10
View File
@@ -0,0 +1,10 @@
Function _wordCompTable();
Begin
return array(
'alignment': 'Alignment',
'shadingcolor': 'Shading.Color',
'style': 'StyleID',
'verticalalignment': 'Valign',
'width': 'Width',
);
End;
+26
View File
@@ -0,0 +1,26 @@
_WordTemplate(alias, fileName);
_WordCopyFromExcel(excelFileName, excelSheetName, startRow, startCol, endRow, endCol);
_WordCopyPicFromExcel(excelFileName, excelSheetName, startRow, startCol, endRow, endCol, picType);
_ExcelChartCopyPic(excelFileName, excelSheetName, picType);
_WordGetCurrentDocument();
_WordGetCurrentRange();
_WordSetCurrnetRange(range);
_WordGetLastRange();
_WordGetLastTable();
_WordGetLastShape();
_WordWrite();
_WordBr();
_WordWriteTable(table, writeIntIndex, writeIntTile, incIntIndex);
_WordWritePicFromFile(fileName);
_WordSetFont(prop, value);
_WordGetFont(prop, value);
_WordAddOleObjectFromFile(fileName, width, height);
_WordLastTableSplit(row, col, rCnt, cCnt);
_WordLastTableMerge(row1, col1, row2, col2);
_WordSetRangeProp(name, value);
_WordGetRangeProp(name, value);
_WordSetLastTableProp(name, value);
_WordGetLastTableProp(name, value);
_WordSetLastTableCellProp(row, col, name, value);
_WordGetLastTableCellProp(row, col, name, value);