diff --git a/Demo/wordHelp.tsl b/Demo/wordHelp.tsl index dc6c21c..ef8393c 100644 --- a/Demo/wordHelp.tsl +++ b/Demo/wordHelp.tsl @@ -160,12 +160,10 @@ Begin _AddTitle(docx, 'TParagraph对象(段落)', 1); //第三段标题 ///TParagraph属性 - _AddTitle(docx, 'TParagraph属性', 2); //第二级标题 - attrs := array(('类别':'缺省w:r元素', '接口':'Run', '说明':'TRun对象')); - formatObj := new TOfficeObj('TwpPr'); - _LoadObjectAttributes(formatObj, attrs, '段落属性', 'Format'); - fontObj := new TOfficeObj('TwrPr'); - _LoadObjectAttributes(fontObj, attrs, '字体属性', 'Font'); + _AddTitle(docx, 'TParagraph属性(段落属性TwpPr对象、字体属性TwrPr对象)', 2); //第二级标题 + attrs := array(('类别':'缺省w:r元素', '接口':'Run', '说明':'TRun对象'), + ('类别':'段落属性', '接口':'Format', '说明':'TwpPr对象'), + ('类别':'字体属性', '接口':'Font', '说明':'TwrPr对象')); _AddClassHelpTable(docx, attrs);//添加表格:TParagraph属性 ///TParagraph方法 @@ -242,11 +240,11 @@ Begin _AddTitle(docx, 'TPicture对象属性', 2); attrs := array(('类别':'图片信息', '接口':'Image', '说明':'二进制内容'), ('类别':'图片信息', '接口':'Descr', '说明':'图像描述'), - ('类别':'图片信息', '接口':'Width', '说明':'图像宽度'), - ('类别':'图片信息', '接口':'Height', '说明':'图像高度') + ('类别':'图片信息', '接口':'Width', '说明':'图像宽度(cm)'), + ('类别':'图片信息', '接口':'Height', '说明':'图像高度(cm)') ); - pPr := new TOfficeObj('TpicsPpr'); - _LoadObjectAttributes(pPr, attrs, '图像属性', 'Format'); + //pPr := new TOfficeObj('TpicsPpr'); + //_LoadObjectAttributes(pPr, attrs, '图像属性', 'Format'); _AddClassHelpTable(docx, attrs);//添加表格:TPicture对象 ///TPicture方法 @@ -624,6 +622,12 @@ Begin conf := _LoadClassInfo(docx.GetPath() + '\\funcext\\TSOffice\\document\\TDocxStyles.tsf', 'TDocxStyles'); _AddFunctionHelpInfo(docx, '' $ paragraph $ '.1.', conf, 3); + _AddTitle(docx, '样式(TDocxStyle)', 2); //第二级标题 + attrs := array(); + formatObj := new TOfficeObj('TDocxStyle'); + _LoadObjectAttributes(formatObj, attrs, '样式', ''); + _AddClassHelpTable(docx, attrs); + println(' >>OK\n'); End; @@ -814,7 +818,7 @@ Function _16_Template(docx); Begin paragraph := sysparams['Test']; _PrintMsg('报告模板(ExecInnerTSL)'); - _AddTitle(docx, 'ExecInnerTSL', 1); + _AddTitle(docx, '报告模板(docx.ExecInnerTSL())', 1); //添加段落 p := TOfficeObj('TParagraph'); @@ -959,9 +963,9 @@ Begin tbl.Format.Borders.Right.themeTint := '99'; //设置列宽 - tbl.ColumnWidth(1, 800); - tbl.ColumnWidth(2, 2000); - tbl.ColumnWidth(3, 2000); + tbl.ColumnWidth(1, 600); + tbl.ColumnWidth(2, 2100); + tbl.ColumnWidth(3, 2100); tbl.ColumnWidth(4, 6000); //设置表格左边距 @@ -969,7 +973,7 @@ Begin tbl.format.IndentType := 'dxa'; //tbl.TblPr.Style := 1; tbl := docx.InsertTable(tbl, -1); - + //设置表头底纹 rows := tbl.Rows(); cols := tbl.Cols(); @@ -989,7 +993,7 @@ Begin cell.Format.Shading.Fill := 'DBEEF3'; cell.Apply(); End; - + //合并单元格 fields := select distinct [1] as 'type' from data where thisrowindex > 0 end; for i:=0 to length(fields)-1 do begin @@ -1092,7 +1096,7 @@ Begin _AddTitle(docx, '附注一:内置对象', 1); //附注标题 ind := 1; - hash := array('TwpPr':1, 'TwrPr':1); + hash := array(); while i < length(r) do Begin attrs := array(); _LoadObjectAttributes(r[i]['obj'], attrs, '属性', ''); diff --git a/DocxFile使用帮助.docx b/DocxFile使用帮助.docx index d91ece6..4d794f0 100644 Binary files a/DocxFile使用帮助.docx and b/DocxFile使用帮助.docx differ diff --git a/ExcelFile使用帮助.xlsx b/ExcelFile使用帮助.xlsx index e71e023..65465b3 100644 Binary files a/ExcelFile使用帮助.xlsx and b/ExcelFile使用帮助.xlsx differ diff --git a/funcext/TSOffice/TOfficeObj.tsf b/funcext/TSOffice/TOfficeObj.tsf index 2fdb279..c98a3b4 100644 --- a/funcext/TSOffice/TOfficeObj.tsf +++ b/funcext/TSOffice/TOfficeObj.tsf @@ -1,4 +1,4 @@ -// Version 1.0.9 +// Version 1.1.0 Function TOfficeObj(n); Begin @@ -3732,10 +3732,23 @@ type THyperLink=class(NodeInfo) XMLTooltip := class(TSXml).CurCodePageToUtf8(str); End; + Property Location read readXMLLocation write writeXMLLocation; + Function readXMLLocation(); + Begin + tmpVal := class(TSXml).Utf8ToCurCodePage(Value('Location')); + if not ifNil(tmpVal) then return tmpVal; + return class(TSXml).Utf8ToCurCodePage(XMLLocation); + End; + + Function writeXMLLocation(str); + Begin + XMLLocation := class(TSXml).CurCodePageToUtf8(str); + End; + Function GetAttrs(); override; Begin HandleAttrs(); - return array(("LinkType", "linkType", LinkType, ""),("LinkUrl", "linkUrl", XMLLinkUrl, ""),("Axis", "ref", Axis, ""),("Display", "display", XMLDisplay, ""),("Tooltip", "tooltip", XMLTooltip, ""),("RId", "r:id", RId, ""),("Location", "location", Location, "")) union ExtAttr; + return array(("LinkType", "linkType", LinkType, ""),("LinkUrl", "linkUrl", XMLLinkUrl, ""),("Axis", "ref", Axis, ""),("Display", "display", XMLDisplay, ""),("Tooltip", "tooltip", XMLTooltip, ""),("RId", "r:id", RId, ""),("Location", "location", XMLLocation, "")) union ExtAttr; End; Function GetChildren(); override; @@ -3751,7 +3764,7 @@ type THyperLink=class(NodeInfo) XMLDisplay; XMLTooltip; RId; - Location; + XMLLocation; //Nodes End; @@ -5593,7 +5606,7 @@ type TRunImpl=class(NodeInfo) Function GetChildren(); override; Begin HandleChildren(); - return array(("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"TwrPr") + return array(("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"字体属性", "class":"TwrPr") ,("field":"fldCharType","name":"w:fldChar","obj":fldCharType,"attrEx":"w:fldCharType","nodeType":"","attrName":"", "desc":"", "class":"") ,("field":"Dirty","name":"w:fldChar","obj":Dirty,"attrEx":"w:dirty","nodeType":"","attrName":"", "desc":"", "class":"") ,("field":"InstrText","name":"w:instrText","obj":InstrText,"attrEx":"","nodeType":"pcdata","attrName":"", "desc":"", "class":"") @@ -5739,7 +5752,7 @@ type TParagraphImpl=class(NodeInfo) Function GetChildren(); override; Begin HandleChildren(); - return array(("field":"pPr","name":pPr.NodeName,"obj":pPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwpPr") + return array(("field":"pPr","name":pPr.NodeName,"obj":pPr,"attrEx":"","nodeType":"","attrName":"", "desc":"段落格式", "class":"TwpPr") ,("field":"markStart","name":markStart.NodeName,"obj":markStart,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TBookMark") ,("field":"Run","name":Run.NodeName,"obj":Run,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TRun") ,("field":"markEnd","name":markEnd.NodeName,"obj":markEnd,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TBookMark") @@ -6307,10 +6320,10 @@ type TDocSectionImpl=class(NodeInfo) ,("field":"pgMar","name":pgMar.NodeName,"obj":pgMar,"attrEx":"","nodeType":"","attrName":"", "desc":"Page Margin设置", "class":"TPageMargin") ,("field":"Page","name":Page.NodeName,"obj":Page,"attrEx":"","nodeType":"","attrName":"", "desc":"页面设置", "class":"TPage") ,("field":"Borders","name":Borders.NodeName,"obj":Borders,"attrEx":"","nodeType":"","attrName":"", "desc":"页面边框属性", "class":"TPageBorders") - ,("field":"titlePg","name":"w:titlePg","obj":titlePg,"attrEx":"","nodeType":"empty","attrName":"", "desc":"", "class":"") - ,("field":"vAlign","name":"w:vAlign","obj":vAlign,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"Type","name":"w:type","obj":Type,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"textDirection","name":"w:textDirection","obj":textDirection,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") + ,("field":"titlePg","name":"w:titlePg","obj":titlePg,"attrEx":"","nodeType":"empty","attrName":"", "desc":"This element specifies whether the parent section in this document shall have a different header and footer for its first page.", "class":"") + ,("field":"vAlign","name":"w:vAlign","obj":vAlign,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"This element specifies the vertical alignment for text on pages in the current section, relative to the top and bottom margins in the main document story on each page.", "class":"") + ,("field":"Type","name":"w:type","obj":Type,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"This element specifies the type of the current section. The section type specifies how the contents of the current section shall be placed relative to the previous section.", "class":"") + ,("field":"textDirection","name":"w:textDirection","obj":textDirection,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"This element specifies the direction of the text flow for this section.", "class":"") ) union ExtNodes; End; @@ -6433,9 +6446,9 @@ type TwTcPr=class(NodeInfo) ,("field":"noWrap","name":"w:noWrap","obj":noWrap,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") ,("field":"tcFitText","name":"w:tcFitText","obj":tcFitText,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") ,("field":"textDirection","name":"w:textDirection","obj":textDirection,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"Del","name":Del.NodeName,"obj":Del,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TOptInfo") - ,("field":"Ins","name":Ins.NodeName,"obj":Ins,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TOptInfo") - ,("field":"cellMerge","name":cellMerge.NodeName,"obj":cellMerge,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TcellMerge") + ,("field":"Del","name":Del.NodeName,"obj":Del,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"TOptInfo") + ,("field":"Ins","name":Ins.NodeName,"obj":Ins,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"TOptInfo") + ,("field":"cellMerge","name":cellMerge.NodeName,"obj":cellMerge,"attrEx":"","nodeType":"","attrName":"", "desc":"单元格属性", "class":"TcellMerge") ,("field":"vAlign","name":"w:vAlign","obj":vAlign,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") ,("field":"vmerge","name":"w:vmerge","obj":vmerge,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") ) union ExtNodes; @@ -6545,7 +6558,7 @@ type TwTrPr=class(NodeInfo) ,("field":"gridBefore","name":"w:gridBefore","obj":gridBefore,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") ,("field":"hidden","name":"w:hidden","obj":hidden,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") ,("field":"tblHeader","name":"w:tblHeader","obj":tblHeader,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"Del","name":Del.NodeName,"obj":Del,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TOptInfo") + ,("field":"Del","name":Del.NodeName,"obj":Del,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"TOptInfo") ) union ExtNodes; End; @@ -6988,7 +7001,7 @@ type TwTblPr=class(NodeInfo) ,("field":"Autofit","name":"w:tblLayout","obj":Autofit,"attrEx":"w:type","nodeType":"","attrName":"", "desc":"", "class":"") ,("field":"CellMar","name":CellMar.NodeName,"obj":CellMar,"attrEx":"","nodeType":"","attrName":"", "desc":"单元格边距设置", "class":"TTblCellMar") ,("field":"Overlap","name":"w:tblOverlap ","obj":Overlap,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"tblpPr","name":tblpPr.NodeName,"obj":tblpPr,"attrEx":"","nodeType":"","attrName":"", "desc":"disable", "class":"TwTblpPr") + ,("field":"tblpPr","name":tblpPr.NodeName,"obj":tblpPr,"attrEx":"","nodeType":"","attrName":"", "desc":"表格样式", "class":"TwTblpPr") ) union ExtNodes; End; @@ -7351,11 +7364,11 @@ type TtblStylePr=class(NodeInfo) Function GetChildren(); override; Begin HandleChildren(); - return array(("field":"pPr","name":pPr.NodeName,"obj":pPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwpPr") - ,("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwrPr") - ,("field":"TrPr","name":TrPr.NodeName,"obj":TrPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwTrPr") - ,("field":"TblPr","name":TblPr.NodeName,"obj":TblPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwTblPr") - ,("field":"TcPr","name":TcPr.NodeName,"obj":TcPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwTcPr") + return array(("field":"pPr","name":pPr.NodeName,"obj":pPr,"attrEx":"","nodeType":"","attrName":"", "desc":"段落格式", "class":"TwpPr") + ,("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"字体属性", "class":"TwrPr") + ,("field":"TrPr","name":TrPr.NodeName,"obj":TrPr,"attrEx":"","nodeType":"","attrName":"", "desc":"表格行属性", "class":"TwTrPr") + ,("field":"TblPr","name":TblPr.NodeName,"obj":TblPr,"attrEx":"","nodeType":"","attrName":"", "desc":"表格属性", "class":"TwTblPr") + ,("field":"TcPr","name":TcPr.NodeName,"obj":TcPr,"attrEx":"","nodeType":"","attrName":"", "desc":"单元格属性", "class":"TwTcPr") ) union ExtNodes; End; @@ -7398,34 +7411,34 @@ type TDocxStyleImpl=class(NodeInfo) Function GetAttrs(); override; Begin HandleAttrs(); - return array(("StyleID", "w:styleId", StyleID, ""),("Default", "w:default", Default, ""),("wType", "w:type", wType, ""),("CustomStyle ", "w:customStyle ", CustomStyle , "")) union ExtAttr; + return array(("StyleID", "w:styleId", StyleID, "样式ID(数字或字符串)。"),("Default", "w:default", Default, "是否缺省样式,如缺省段落、缺省表格样式"),("wType", "w:type", wType, "样式类型(paragraph、chartacter、table)"),("CustomStyle ", "w:customStyle ", CustomStyle , "disable")) union ExtAttr; End; Function GetChildren(); override; Begin HandleChildren(); - return array(("field":"Name","name":"w:name","obj":Name,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"Aliases","name":"w:aliases","obj":Aliases,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"AutoRedefine","name":"w:autoRedefine","obj":AutoRedefine,"attrEx":"","nodeType":"empty","attrName":"", "desc":"", "class":"") - ,("field":"BasedOn","name":"w:basedOn","obj":BasedOn,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"Hidden","name":"w:hidden","obj":Hidden,"attrEx":"","nodeType":"empty","attrName":"", "desc":"", "class":"") - ,("field":"Link","name":"w:link","obj":Link,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"Locked","name":"w:locked","obj":Locked,"attrEx":"","nodeType":"empty","attrName":"", "desc":"", "class":"") - ,("field":"Next","name":"w:b","obj":Next,"attrEx":"","nodeType":"empty","attrName":"", "desc":"", "class":"") - ,("field":"Personal","name":"w:personal","obj":Personal,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"PersonalCompose","name":"w:personalCompose","obj":PersonalCompose,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"PersonalReply","name":"w:personalReply","obj":PersonalReply,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"QFormat","name":"w:qFormat","obj":QFormat,"attrEx":"","nodeType":"empty","attrName":"", "desc":"", "class":"") - ,("field":"TblStyle","name":TblStyle.NodeName,"obj":TblStyle,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TtblStylePr") - ,("field":"pPr","name":pPr.NodeName,"obj":pPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwpPr") - ,("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwrPr") - ,("field":"TrPr","name":TrPr.NodeName,"obj":TrPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwTrPr") - ,("field":"TblPr","name":TblPr.NodeName,"obj":TblPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwTblPr") - ,("field":"TcPr","name":TcPr.NodeName,"obj":TcPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwTcPr") - ,("field":"Rsid","name":"w:rsid","obj":Rsid,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"SemiHidden","name":"w:semiHidden","obj":SemiHidden,"attrEx":"","nodeType":"empty","attrName":"", "desc":"", "class":"") - ,("field":"UiPriority","name":"w:uiPriority","obj":UiPriority,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"UnhideWhenUsed","name":"w:unhideWhenUsed","obj":UnhideWhenUsed,"attrEx":"","nodeType":"empty","attrName":"", "desc":"", "class":"") + return array(("field":"Name","name":"w:name","obj":Name,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"样式名称", "class":"") + ,("field":"Aliases","name":"w:aliases","obj":Aliases,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"This element specifies the set of alternative names for the parent style definition.", "class":"") + ,("field":"AutoRedefine","name":"w:autoRedefine","obj":AutoRedefine,"attrEx":"","nodeType":"empty","attrName":"", "desc":"This element specifies whether an application shall automatically modify this style when the contents of an entire paragraph in the document with this style applied are modified, ensuring that although only a single instance of text with this style was modified, that change is stored on the style and therefore propagated to all locations where the style is in use.", "class":"") + ,("field":"BasedOn","name":"w:basedOn","obj":BasedOn,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"This element specifies the style ID of the parent style from which this style inherits in the style inheritance. The style inheritance refers to a set of styles which inherit from one another to produce the resulting set of properties for a single style. The val attribute of this element specifies the styleId attribute for the parent style in the style inheritance.", "class":"") + ,("field":"Hidden","name":"w:hidden","obj":Hidden,"attrEx":"","nodeType":"empty","attrName":"", "desc":"This element specifies whether this style shall be hidden from any and all user interfaces when this document is loaded by an application. If this element is set, then this style may be used to format content (i.e. any content which references this style shall have its properties as normal), but the style shall be hidden from all user interface associated with that application. [Note: This setting is typically used to hide styles which are being used internally by an application which should not be used as formatting in a typical case. end note]", "class":"") + ,("field":"Link","name":"w:link","obj":Link,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"Linked Style Reference", "class":"") + ,("field":"Locked","name":"w:locked","obj":Locked,"attrEx":"","nodeType":"empty","attrName":"", "desc":"This element specifies whether an application shall prevent the use of this style when this document is loaded and/or modified. If this element is set, then this style may be used to format existing content (i.e. any content which references this style shall have its properties as normal), but new instances of the style shall be prevented from being applied via all mechanisms associated with that application.", "class":"") + ,("field":"Next","name":"w:b","obj":Next,"attrEx":"","nodeType":"empty","attrName":"", "desc":"Style For Next Paragraph", "class":"") + ,("field":"Personal","name":"w:personal","obj":Personal,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"This element specifies that the parent style, when in use in the context of an e-mail message, was used by default to format all message text from one or more users. [Note: This setting does not provide any additional semantic about the style, but may be used in the context of e-mail to automatically reformat the contents of the e-mail message while ignoring any content to which styles were deliberately applied (since this style was implicitly applied to message text without user interaction). end note]", "class":"") + ,("field":"PersonalCompose","name":"w:personalCompose","obj":PersonalCompose,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"This element specifies that the parent style, when in use in the context of an e-mail message, may be used by default to format new message text within the e-mail message. [Note: This setting does not provide any additional semantic about the style, but may be used in the context of e-mail to automatically format the contents of new test in the e-mail message. end note]", "class":"") + ,("field":"PersonalReply","name":"w:personalReply","obj":PersonalReply,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"This element specifies that the parent style, when in use in the context of an e-mail message, may be used by default to format existing message text within the e-mail message when a new reply is generated. [Note: This setting does not provide any additional semantic about the style, but may be used in the context of e-mail to automatically format the contents of existing test in the e-mail message. end note]", "class":"") + ,("field":"QFormat","name":"w:qFormat","obj":QFormat,"attrEx":"","nodeType":"empty","attrName":"", "desc":"This element specifies whether this style shall be treated as a primary style when this document is loaded by an application. If this element is set, then this style has been designated as being particularly important for the current document, and this information may be used by an application in any means desired. [Note: This setting does not imply any behavior for the style, only that the style is of particular significance for this document. end note]", "class":"") + ,("field":"TblStyle","name":TblStyle.NodeName,"obj":TblStyle,"attrEx":"","nodeType":"","attrName":"", "desc":"表格样式", "class":"TtblStylePr") + ,("field":"pPr","name":pPr.NodeName,"obj":pPr,"attrEx":"","nodeType":"","attrName":"", "desc":"段落格式", "class":"TwpPr") + ,("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"字体属性", "class":"TwrPr") + ,("field":"TrPr","name":TrPr.NodeName,"obj":TrPr,"attrEx":"","nodeType":"","attrName":"", "desc":"表格行属性", "class":"TwTrPr") + ,("field":"TblPr","name":TblPr.NodeName,"obj":TblPr,"attrEx":"","nodeType":"","attrName":"", "desc":"表格样式", "class":"TwTblPr") + ,("field":"TcPr","name":TcPr.NodeName,"obj":TcPr,"attrEx":"","nodeType":"","attrName":"", "desc":"单元格样式", "class":"TwTcPr") + ,("field":"Rsid","name":"w:rsid","obj":Rsid,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"disable", "class":"") + ,("field":"SemiHidden","name":"w:semiHidden","obj":SemiHidden,"attrEx":"","nodeType":"empty","attrName":"", "desc":"This element specifies whether this style shall be hidden from the main user interface when this document is loaded by an application. If this element is set, then this style may be used to format content (i.e. any content which references this style shall have its properties as normal), but the style shall be hidden from the main user interface associated with that application.", "class":"") + ,("field":"UiPriority","name":"w:uiPriority","obj":UiPriority,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"This element specifies a number which may be used to sort the set of style definitions in a user interface when this document is loaded by an application and the recommended setting is specified in the stylePaneSortMethod element (§2.15.1.87). If this element is set, then this priority shall be used to sort all available styles in ascending value order.", "class":"") + ,("field":"UnhideWhenUsed","name":"w:unhideWhenUsed","obj":UnhideWhenUsed,"attrEx":"","nodeType":"empty","attrName":"", "desc":"This element specifies whether the semiHidden property (§2.7.3.16) shall be removed when this style is used by the content of the document. If this element is set, then an application shall ensure that even if the semiHidden element is specified on a style, that this property is removed when the document is resaved if the style is referenced by any content in the document.", "class":"") ) union ExtNodes; End; @@ -7532,7 +7545,7 @@ type TStdPr=class(NodeInfo) Function GetChildren(); override; Begin HandleChildren(); - return array(("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwrPr") + return array(("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"字体属性", "class":"TwrPr") ,("field":"ID","name":"w:id","obj":ID,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") ,("field":"docPartObj","name":docPartObj.NodeName,"obj":docPartObj,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TDocPartObj") ) union ExtNodes; @@ -7576,7 +7589,7 @@ type TStdEndPr=class(NodeInfo) Function GetChildren(); override; Begin HandleChildren(); - return array(("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TwrPr") + return array(("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"字体属性", "class":"TwrPr") ) union ExtNodes; End; @@ -7814,17 +7827,17 @@ type TLevel=class(NodeInfo) Function GetAttrs(); override; Begin HandleAttrs(); - return array(("ilvl", "w:ilvl", ilvl, ""),("tentative", "w:tentative", tentative, "")) union ExtAttr; + return array(("ilvl", "w:ilvl", ilvl, "内容是否包含小数。"),("tentative", "w:tentative", tentative, "")) union ExtAttr; End; Function GetChildren(); override; Begin HandleChildren(); - return array(("field":"start","name":"w:start","obj":start,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"numFmt","name":"w:numFmt","obj":numFmt,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"lvlText","name":"w:lvlText","obj":lvlText,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") + return array(("field":"start","name":"w:start","obj":start,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"给定编号级别定义中父编号级别使用的编号的起始值。", "class":"") + ,("field":"numFmt","name":"w:numFmt","obj":numFmt,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"编号类型(单极、多级、项目编号等)。", "class":"") + ,("field":"lvlText","name":"w:lvlText","obj":lvlText,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"编号文本内容格式,如(%1.%2.%3.%4)。", "class":"") ,("field":"lvlJc","name":"w:lvlJc","obj":lvlJc,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"pPr","name":pPr.NodeName,"obj":pPr,"attrEx":"","nodeType":"","attrName":"", "desc":"段落属性", "class":"TwpPr") + ,("field":"pPr","name":pPr.NodeName,"obj":pPr,"attrEx":"","nodeType":"","attrName":"", "desc":"段落格式", "class":"TwpPr") ,("field":"rPr","name":rPr.NodeName,"obj":rPr,"attrEx":"","nodeType":"","attrName":"", "desc":"字体属性", "class":"TwrPr") ) union ExtNodes; End; @@ -7866,16 +7879,16 @@ type TNumStyleImpl=class(NodeInfo) Function GetAttrs(); override; Begin HandleAttrs(); - return array(("abstractNumId", "w:abstractNumId", abstractNumId, "")) union ExtAttr; + return array(("abstractNumId", "w:abstractNumId", abstractNumId, "latentStyles编号ID(编号段落的外观和行为)")) union ExtAttr; End; Function GetChildren(); override; Begin HandleChildren(); - return array(("field":"nsid","name":"w:nsid","obj":nsid,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"multiLevelType","name":"w:multiLevelType","obj":multiLevelType,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"tmpl","name":"w:tmpl","obj":tmpl,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"", "class":"") - ,("field":"lvl","name":lvl.NodeName,"obj":lvl,"attrEx":"","nodeType":"","attrName":"", "desc":"", "class":"TLevel") + return array(("field":"nsid","name":"w:nsid","obj":nsid,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"disable", "class":"") + ,("field":"multiLevelType","name":"w:multiLevelType","obj":multiLevelType,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"编号类型", "class":"") + ,("field":"tmpl","name":"w:tmpl","obj":tmpl,"attrEx":"w:val","nodeType":"","attrName":"", "desc":"该元素指定了一个唯一的十六进制代码,该代码可用于确定应用程序用户界面中显示该抽象编号定义的位置。", "class":"") + ,("field":"lvl","name":lvl.NodeName,"obj":lvl,"attrEx":"","nodeType":"","attrName":"", "desc":"编号级别的外观和行为", "class":"TLevel") ) union ExtNodes; End; @@ -8181,7 +8194,7 @@ Type DocObject = Class node2 := node.InsertEndChild('element', 'w:r'); End; run := new TRun(node2); - run.SetText(obj.InsText, true); + run.SetText(obj.InsText_, true); obj.Init(node); return true; End; @@ -8467,6 +8480,17 @@ Type TRevision = Class(DocObject, TRevisionImpl) Class(TRevisionImpl).Create(nil, name_); End; + Property InsText read readInsText write writeInsText; + Function readInsText(); + Begin + return class(TSXml).Utf8ToCurCodePage(InsText_); + End; + + Function writeInsText(txt); + Begin + InsText_ := class(TSXml).CurCodePageToUtf8(txt); + End; + ///修订类型 ///返回:string, 删除:'del'、添加:'ins' Function Act(); @@ -8522,7 +8546,7 @@ Type TRevision = Class(DocObject, TRevisionImpl) CommentID:integer; sPos:integer; SelectLength:integer; - InsText:string; + InsText_:string; End; Type TDocComment = Class(TDocCommentImpl) @@ -9058,15 +9082,6 @@ Type TRun = Class(DocObject, TRunImpl) AddText(str, true); End; - Function _preserve(str); - Begin - cnt := length(str); - spaceArr := array(' ',' '); - if cnt and (str[1] in spaceArr or (cnt > 1 and str[cnt] in spaceArr)) then - return true; - return false; - End; - Function _insertText(txt, first); Begin lines := str2array(txt,'\n'); @@ -10814,86 +10829,6 @@ Type TDocumentBody = Class(DocObject) return tbl; End; - ///创建数据表 - ///data: table,数据表 - ///[IncludeHeader: bool] 是否包括表头,默认FALSE - ///[IncludeIndex: bool] 是否自动添加索引号,默认FALSE - ///返回: tbl TTable对象 - Function CreateTable(data, IncludeHeader, IncludeIndex); - Begin - if not IsTable(data) then - raise "Invalid Data."; - fields := FieldNames(data); - if IsTable(fields) then Begin - r := nils(length(data),length(fields)); - r[:,:] := data; - data := r; - End; - 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 - fields := array("Index") union fields; - data := array(fields) union data; - End; - tbl := new TTable(); - //tbl.TblPr.StyleId := 'Normal Table'; - tbl.TblPr.Width := 0; - tbl.TblPr.WidthType := 'auto'; - tbl.TblPr.Borders.Top.Val := 'single'; - tbl.TblPr.Borders.Left.Val := 'single'; - tbl.TblPr.Borders.Bottom.Val := 'single'; - tbl.TblPr.Borders.Right.Val := 'single'; - tbl.TblPr.Borders.InsideH.Val := 'single'; - tbl.TblPr.Borders.InsideV.Val := 'single'; - tbl.TblPr.CellMar.Top := 0; - tbl.TblPr.CellMar.Left := 108; - tbl.TblPr.CellMar.Bottom := 0; - tbl.TblPr.CellMar.Right := 108; - tbl.TblPr.CellMar.TopType := 'dxa'; - tbl.TblPr.CellMar.LeftType := 'dxa'; - tbl.TblPr.CellMar.BottomType := 'dxa'; - tbl.TblPr.CellMar.RightType := 'dxa'; - //tbl.TblPr.FirstColumn := 1; - //tbl.TblPr.FirstRow := 1; - //tbl.TblPr.LastColumn := 0; - //tbl.TblPr.LastRow := 0; - //tbl.TblPr.NoVBand := 1; - //tbl.TblPr.NoHBand := 0; - //tbl.TblPr.Val := '04A0'; - - width := getBlockWidth(); - [rowCount, colCount] := MSize(data); - colWidth := colCount ? integer(width / colCount) : 0; - gridArr := array(); - for i:=0 to colCount-1 do Begin - gcol := new TwGridCol(); - gcol.W := colWidth; - gridArr union= array(('name':'w:gridCol','obj':gcol,'attrEx':'','nodeType':'','attrName':'')); - End; - tbl.TblGrid.GridCol := gridArr; - - trArr := array(); - for i:=0 to length(data)-1 do Begin - tr := new TWtr(); - trArr union= array(('name':'w:tr','obj':tr,'attrEx':'','nodeType':'','attrName':'')); - tcArr := array(); - for j:=0 to colCount-1 do Begin - tc := new TCell(); - tcArr union= array(('name':'w:tc','obj':tc,'attrEx':'','nodeType':'','attrName':'')); - tc.TcPr.Width := colWidth; - tc.TcPr.Type := 'dxa'; - tc.SetText(data[i, j]); - End; - tr.Tc := tcArr; - End; - tbl.TR := trArr; - return tbl; - End; - ///插入数据表 ///tbl: TTable对象 ///[posOpt: 段落位置],0 在DOCX文件开头;-1 文件尾;N 在第N段之后;DocumentPart对象 在posOpt之后新添加表格 @@ -10905,31 +10840,84 @@ Type TDocumentBody = Class(DocObject) if ifObj(tblBorders) or ifObj(tblCellMar) then Begin borders := ifObj(tblBorders) ? tblBorders.Marshal() : nil; cellmar := ifObj(tblCellMar) ? tblCellMar.Marshal() : nil; - tr := tbl.node_.FirstChildElement('w:tr'); - while ifObj(tr) do Begin - if ifObj(tblCellMar) then Begin - c := class(TSXml).GetNode(tr, 'w:tblPrEx/w:tblCellMar', 'first'); - class(TSXml).UpdateNode(c, cellmar[0]['attributes'], cellmar[0]['children']); + End; + defaultParagraph := new TParagraph(); + defaultParagraph.pPr.rPr.Lang := 'en-US'; + defaultParagraph.pPr.rPr.eastAsia := 'zh-CN'; + defaultParagraph.Run.rPr.Lang := 'en-US'; + defaultParagraph.Run.rPr.eastAsia := 'zh-CN'; + defaultpPr := defaultParagraph.pPr.Marshal(); + defaultrPr := defaultParagraph.Run.rPr.Marshal(); + + for i:=0 to length(tbl.Data_)-1 do Begin + trNode := tbl.node_.InsertEndChild('element', 'w:tr'); + multiLine := false; + if ifstring(tbl.Data_[i, j]) and Pos('\n', tbl.Data_[i, j]) then + multiLine := true; + for j:=0 to tbl.colCount_-1 do Begin + //对象太多的话,对象效率奇慢,优化掉 + //tc := new TCell(); + //tc.TcPr.Width := tbl.TblGrid.GridCol[j]['obj'].W; + //tc.TcPr.Type := 'dxa'; + //tc.SetText(tbl.Data_[i, j]); + //trNode.InsertEndChild(tc.Marshal()); + //tc := 0; + + tcNode := trNode.InsertEndChild('element', 'w:tc'); + tcPrNode := tcNode.InsertEndChild('element', 'w:tcPr'); + tcWNode := tcPrNode.InsertEndChild('element', 'w:tcW'); + tcWNode.SetAttribute('w:w', tbl.TblGrid.GridCol[j]['obj'].W); + tcWNode.SetAttribute('w:type', 'dxa'); + if multiLine then Begin + defaultParagraph.node_ := nil; + defaultParagraph.Run.ClearText(); + defaultParagraph.Run.SetText(tbl.Data_[i, j]); + tcNode.InsertEndChild(defaultParagraph.Marshal()); + End + else Begin + pNode := tcNode.InsertEndChild('element', 'w:p'); + pNode.InsertEndChild(defaultpPr); + rNode := pNode.InsertEndChild('element', 'w:r'); + rNode.InsertEndChild(defaultrPr); + tNode := rNode.InsertEndChild('element','w:t', tbl.Data_[i, j]); + if _preserve(tbl.Data_[i, j]) then + tNode.SetAttribute('xml:space', 'preserve'); End; - if ifObj(tblBorders) then Begin - b := class(TSXml).GetNode(tr, 'w:tblPrEx/w:tblBorders', 'first'); - class(TSXml).UpdateNode(b, borders[0]['attributes'], borders[0]['children']); - End; - tr := tr.NextElement('w:tr'); +(* + + + + + + + + + + + + + + + Index + + + +*) + End; + if ifObj(tblCellMar) then Begin + c := class(TSXml).GetNode(trNode, 'w:tblPrEx/w:tblCellMar', 'first'); + class(TSXml).UpdateNode(c, cellmar[0]['attributes'], cellmar[0]['children']); + End; + if ifObj(tblBorders) then Begin + b := class(TSXml).GetNode(trNode, 'w:tblPrEx/w:tblBorders', 'first'); + class(TSXml).UpdateNode(b, borders[0]['attributes'], borders[0]['children']); End; End; node_.Parent().SetAttribute('mc:Ignorable', 'w14 w15 wp14'); node_.Parent().SetAttribute('xmlns:w15', 'http://schemas.microsoft.com/office/word/2012/wordml'); - //last := node_.InsertAfterChild(tbl.node_, 'element', 'w:p'); _set_lastParagraph_(tbl.node_); p := new TTable(tbl.node_); - //node := node_.FirstChildElement('w:sectPr'); - //node.DeleteAttribute('w:rsidSect'); - //node.DeleteAttribute('w:rsidRPr'); - //node.DeleteAttribute('w:rsidR'); - //cols := node.FirstChildElement('w:cols'); - //cols.SetAttribute('w:num',1); return p; End; @@ -11554,19 +11542,6 @@ Type TDocumentBody = Class(DocObject) txt := ReplaceStr(txt, '\n', ''); return txt; End; - - Function getBlockWidth(); - Begin - sectPr := node_.FirstChildElement('w:sectPr'); - try - width := sectPr.FirstChildElement('w:pgSz').GetAttribute('w:w'); - left := sectPr.FirstChildElement('w:pgMar').GetAttribute('w:left'); - right := sectPr.FirstChildElement('w:pgMar').GetAttribute('w:right'); - return strtoint(width) - strtoint(left) - strtoint(right); - except - End; - return strtoint(width); - End; Function _set_lastParagraph_(node); Begin @@ -11748,6 +11723,26 @@ Type TDocSection = Class(DocObject, TDocSectionImpl) node := node_.InsertFirstChild('element', headerFooter = 'header' ? 'w:headerReference' : 'w:footerReference'); node.SetAttribute('w:type', hfType); node.SetAttribute('r:id', 'rId'$rid); + if hfType = 'first' then Begin + docGridNode := node_.FirstChildElement('w:docGrid'); + titlePg := node_.FirstChildElement('w:titlePg'); + if not ifObj(titlePg) then Begin + if ifObj(docGridNode) then + titlePg := node_.InsertBeforeChild(docGridNode,'element','w:titlePg'); + else + titlePg := node_.InsertEndChild('element','w:titlePg'); + End; + End; + + if hfType = 'even' then Begin + settingsXml := zipfile_.Get('word/settings.xml'); + if ifObj(settingsXml) then Begin + evenObj := settingsXml.FirstChildElement('w:settings').FirstChildElement('w:evenAndOddHeaders'); + if not ifObj(evenObj) then + evenObj := settingsXml.FirstChildElement('w:settings').InsertFirstChild('element','w:evenAndOddHeaders'); + evenObj.SetAttribute('w:val', 1); + End; + End; return new TDocHeaderFooter(rid, zipfile_.Get(fname), name);//返回页脚、页眉对象 End; @@ -11979,12 +11974,13 @@ Type TTable = Class(DocObject, TTableImpl) col := row.FirstChildElement('w:tc'); iCol := 0; while ifObj(col) do Begin - c := new TCell(col); - cells_[iRow, iCol] := c; + //c := new TCell(col); + cells_[iRow, iCol] := array(col, 0); iCol ++; mergeSpan := _getVSpan(col);//合并单元格 if mergeSpan > 0 then Begin - c.mergeSpan_ := mergeSpan; + //c.mergeSpan_ := mergeSpan; + cells_[iRow, iCol, 1] := mergeSpan; for j:=1 to mergeSpan-1 do Begin cells_[iRow, iCol] := nil; iCol ++; @@ -11998,6 +11994,69 @@ Type TTable = Class(DocObject, TTableImpl) End; End; + ///设置表格数据 + ///data: table,数据表 + ///[IncludeHeader: bool] 是否包括表头,默认FALSE + ///[IncludeIndex: bool] 是否自动添加索引号,默认FALSE + Function SetData(docx, data, IncludeHeader, IncludeIndex); + Begin + if not IsTable(data) then + raise "Invalid Data."; + fields := FieldNames(data); + if IsTable(fields) then Begin + r := nils(length(data),length(fields)); + r[:,:] := data; + data := r; + End; + 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 + fields := array("Index") union fields; + data := array(fields) union data; + End; + Data_ := data; + //TblPr.StyleId := 'Normal Table'; + TblPr.Width := 0; + TblPr.WidthType := 'auto'; + TblPr.Borders.Top.Val := 'single'; + TblPr.Borders.Left.Val := 'single'; + TblPr.Borders.Bottom.Val := 'single'; + TblPr.Borders.Right.Val := 'single'; + TblPr.Borders.InsideH.Val := 'single'; + TblPr.Borders.InsideV.Val := 'single'; + TblPr.CellMar.Top := 0; + TblPr.CellMar.Left := 108; + TblPr.CellMar.Bottom := 0; + TblPr.CellMar.Right := 108; + TblPr.CellMar.TopType := 'dxa'; + TblPr.CellMar.LeftType := 'dxa'; + TblPr.CellMar.BottomType := 'dxa'; + TblPr.CellMar.RightType := 'dxa'; + //TblPr.FirstColumn := 1; + //TblPr.FirstRow := 1; + //TblPr.LastColumn := 0; + //TblPr.LastRow := 0; + //TblPr.NoVBand := 1; + //TblPr.NoHBand := 0; + //TblPr.Val := '04A0'; + + width := getBlockWidth(docx); + [rowCount, cnt] := MSize(data); + colCount_ := cnt; + colWidth_ := colCount_ ? integer(width / colCount_) : 0; + gridArr := array(); + for i:=0 to colCount_-1 do Begin + gcol := new TwGridCol(); + gcol.W := colWidth_; + gridArr union= array(('name':'w:gridCol','obj':gcol,'attrEx':'','nodeType':'','attrName':'')); + End; + TblGrid.GridCol := gridArr; + End; + Property Format read readFormat; Function readFormat(); Begin @@ -12033,21 +12092,18 @@ Type TTable = Class(DocObject, TTableImpl) Function Cell(row, col); Begin if row > length(cells_) then return nil; - return cells_[row-1, col-1]; + c := cells_[row-1, col-1]; + if ifNil(c) then return nil; + cellObj := new TCell(c[0]); + cellObj.mergeSpan_ := c[1]; + return cellObj; End; ///设置列宽 Function ColumnWidth(n, wth); Begin - if n >0 and n <= length(TblGrid.GridCol) then Begin + if n >0 and n <= length(TblGrid.GridCol) then TblGrid.GridCol[n-1]['obj'].W := wth; - for i:=0 to length(TR)-1 do Begin - r := TR[i]['obj']; - if n <= length(r.TC) then Begin - r.TC[n-1]['obj'].TcPr.Width := wth; - End; - End; - End; End; ///合并单元格 @@ -12200,8 +12256,24 @@ Type TTable = Class(DocObject, TTableImpl) return -1; End; + Function getBlockWidth(docx); + Begin + sectPr := docx.Body().node_.FirstChildElement('w:sectPr'); + try + width := sectPr.FirstChildElement('w:pgSz').GetAttribute('w:w'); + left := sectPr.FirstChildElement('w:pgMar').GetAttribute('w:left'); + right := sectPr.FirstChildElement('w:pgMar').GetAttribute('w:right'); + return strtoint(width) - strtoint(left) - strtoint(right); + except + End; + return strtoint(width); + End; + iCol_:integer; cells_; + Data_; + colCount_; + colWidth_; End; Type TCoreProperties = Class(DocObject) @@ -12620,6 +12692,17 @@ Begin return println('rPr is null'); println('sz={},szCs={},hint={},eastAsia={}', rPr.Size,rPr.szCs,rPr.rFont.hint,rPr.rFont.eastAsia); +End; + +//文本前后是否包含空格 +Function _preserve(str); +Begin + if not ifstring(str) then return false; + cnt := length(str); + spaceArr := array(' ',' '); + if cnt and (str[1] in spaceArr or (cnt > 1 and str[cnt] in spaceArr)) then + return true; + return false; End;/////////////////////////////////////////////////////////////////////////////////////////// ///XLSX文档实现 diff --git a/funcext/TSOffice/TSDocxFile.tsf b/funcext/TSOffice/TSDocxFile.tsf index ef36f05..e04f764 100644 --- a/funcext/TSOffice/TSDocxFile.tsf +++ b/funcext/TSOffice/TSDocxFile.tsf @@ -1,4 +1,4 @@ -// Version 1.0.9 +// Version 1.1.0 Type TSDocxFile = Class ///Version: V1.0 2022-09-20 @@ -184,7 +184,9 @@ Type TSDocxFile = Class ///返回: TTable对象 Function CreateTable(data, IncludeHeader, IncludeIndex); Begin - return document_.Body().CreateTable(data, IncludeHeader, IncludeIndex); + tbl := TOfficeObj('TTable'); + tbl.SetData(self, data, IncludeHeader, IncludeIndex); + return tbl; End; ///插入数据表 @@ -385,7 +387,7 @@ Type TSDocxFile = Class return document_.Body().GetHeadingListImpl(self, nil, UpperHeadingLevel, LowerHeadingLevel, nil, true); End; - ///返回Document对象 + //返回Document对象 Function Document(); Begin return document_; @@ -407,8 +409,8 @@ Type TSDocxFile = Class return numberingObj_; End; - ///执行word文档内嵌tsl代码 - ///返回:[err,tslFuncCount,errArr]: err 执行错误TSL代码段次数,tslFuncCount TSL代码段总数,errArr 执行TSL错误信息(包括代码、错误信息) + ///执行word文档内嵌tsl代码(执行内嵌脚本的环境字符集为GBK) + ///返回:[err,tslFuncCount,errArr]: err 执行错误TSL代码段次数,tslFuncCount TSL代码段总数,errArr 执行TSL错误信息(array(('code':'代码', 'err':'错误信息'))) Function ExecInnerTSL(); Begin return Body().ExecInnerTSL(self); diff --git a/funcext/TSOffice/TSExcelFile.tsf b/funcext/TSOffice/TSExcelFile.tsf index fc9e2de..b2050ac 100644 --- a/funcext/TSOffice/TSExcelFile.tsf +++ b/funcext/TSOffice/TSExcelFile.tsf @@ -1,4 +1,4 @@ -// Version 1.0.9 +// Version 1.1.0 Type TSExcelFile = Class ///Version: V1.0 2022-08-08 @@ -791,6 +791,14 @@ Type TSExcelFile = Class return o.GetAppProps(); End; + ///复制Sheet + ///sourceSheet: 源工作表 + ///destSheet: 目的工作表 + Function CopySheet(sourceSheet, destSheet); + Begin + return workbook_.CopySheet(class(TSXml).CurCodePageToUtf8(sourceSheet), class(TSXml).CurCodePageToUtf8(destSheet)); + End; + Function WorkBook(); Begin return workbook_; diff --git a/funcext/TSOffice/TSUtils/TSXml.tsf b/funcext/TSOffice/TSUtils/TSXml.tsf index 9773e80..cca1965 100644 --- a/funcext/TSOffice/TSUtils/TSXml.tsf +++ b/funcext/TSOffice/TSUtils/TSXml.tsf @@ -20,9 +20,13 @@ Type TSXml = Class 'workbook_rels':('FileName':'xl/_rels/workbook.xml.rels','Template':''), 'sheet_rels':('FileName':'','Template':''), 'drawing_rels':('FileName':'','Template':''), - 'SheetContentType':('FileName':'','Template':'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml'), + 'sheetContentType':('FileName':'','Template':'application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml'), 'RelationshipWorkSheet':('FileName':'','Template':'http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet'), 'table1':('FileName':'xl/tables/table1.xml','Template':'
'), + 'tableContentType':('FileName':'','Template':'application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml'), + 'commentContentType':('FileName':'','Template':'application/vnd.openxmlformats-officedocument.spreadsheetml.comments+xml'), + 'drawingContentType':('FileName':'','Template':'application/vnd.openxmlformats-officedocument.drawing+xml'), + 'chartContentType':('FileName':'','Template':'application/vnd.openxmlformats-officedocument.drawingml.chart+xml'), ); End diff --git a/funcext/TSOffice/document/TDocxStyles.tsf b/funcext/TSOffice/document/TDocxStyles.tsf index 14a0713..a14099b 100644 --- a/funcext/TSOffice/document/TDocxStyles.tsf +++ b/funcext/TSOffice/document/TDocxStyles.tsf @@ -63,8 +63,8 @@ Type TDocxStyles = Class return idMap_[ id ]; End; - ///返回全部LatentStyles对象列表 - ///返回:TDocxStyle对象列表 + //返回全部LatentStyles对象列表 + //返回:TDocxStyle对象列表 Function LatentStyles(); Begin r := array(); @@ -76,7 +76,6 @@ Type TDocxStyles = Class while ifObj(node) do Begin o := TOfficeObj('TDocxStyle'); o.Init(node); - o.name_ := node.GetAttribute('w:name'); r[ length(r) ] := o; node := node.NextElement('w:lsdException'); End; diff --git a/funcext/TSOffice/template/faq.txt b/funcext/TSOffice/template/faq.txt index f1ec09f..00cd492 100644 --- a/funcext/TSOffice/template/faq.txt +++ b/funcext/TSOffice/template/faq.txt @@ -40,4 +40,14 @@ Apply()函数可以修改属性值,例如: ... p.Run.SetText('系统可以自动识别这里的中文字符集(utf8或gbk)!'); ★不设置,默认当前字符集为UTF8 - \ No newline at end of file + +*报告模板功能(TDocxFile::ExecInnerTSL)中,Word中执行[TSL]...[/TSL]时的字符集是啥? + 是GBK。 + +*TDocxFile::NewFile()创建的缺省word文档格式说明: + 1.5倍行距、默认5号字体、宋体。 + +*缺省文档格式不是我想要的,怎么办? + ★用户可以利用word(或wps)生成自己想要格式的空文档,调用TDocxFile::OpenFile()打开即可。 + ★用户甚至可以设计好文档封面、目录、页脚、页眉,再调用TDocxFile::OpenFile()打开。 + ★用户可以在word文档中内嵌TSL代码,调用TDocxFile::ExecInnerTSL()操作word文档。 \ No newline at end of file diff --git a/funcext/TSOffice/worksheet/xlsxTable.tsf b/funcext/TSOffice/worksheet/xlsxTable.tsf index 69f054e..f36ca8e 100644 --- a/funcext/TSOffice/worksheet/xlsxTable.tsf +++ b/funcext/TSOffice/worksheet/xlsxTable.tsf @@ -27,7 +27,7 @@ Type xlsxTable = Class table.Xr3 := 'http://schemas.microsoft.com/office/spreadsheetml/2016/revision3'; table.Id := table_id; table.Name := '表' $ table_id; - table.DisplayName := format.TableName ? format.TableName : table.Name; + table.DisplayName := class(xlsxTable).GenerateValidDisplayName(format.TableName, tableid); table.Ref := topLeft $ ':' $ bottomRight; table.HeaderRowCount := format.HeaderRowCount ? '1' : nil; table.TotalsRowShown := format.TotalsRowShown ? '1' : '0'; @@ -67,6 +67,20 @@ Type xlsxTable = Class End + class Function GenerateValidDisplayName(name, nameId); + Begin + if ifnil(name) then name := '表' $ nameId; + if TOfficeApi().Get('Table-' $ name) then + begin + new_name := '表' $ nameId; + while TOfficeApi().Get('Table-' $ new_name) do new_name := '表' $ ++nameId; + TOfficeApi().Set('Table-' $ new_name, true); + return new_name; + end + TOfficeApi().Set('Table-' $ name, true); + return name; + End + private Function getTableColumnsXmlString(begCol, endCol, row, includeHeader); Begin @@ -105,7 +119,7 @@ private excel_.zip().Add(table_name, class(TSXml).XmlHeader() + ""); class(TSXml).AddRelationshipRid(sheet_rels_file, table_target, 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/table', 'rId' $ rid); content_xml := excel_.WorkBook().GetXmlFileObj(class(TSXml).GetFileName('Content_Types')); - class(TSXml).AddOverrideContentType(content_xml, '/' + table_name, 'application/vnd.openxmlformats-officedocument.spreadsheetml.table+xml'); + class(TSXml).AddOverrideContentType(content_xml, '/' + table_name, class(TSXml).GetTemplate('tableContentType')); return array(rid, table_id, table_name); End diff --git a/funcext/TSOffice/worksheet/xlsxWorkBook.tsf b/funcext/TSOffice/worksheet/xlsxWorkBook.tsf index 4432734..77e75a2 100644 --- a/funcext/TSOffice/worksheet/xlsxWorkBook.tsf +++ b/funcext/TSOffice/worksheet/xlsxWorkBook.tsf @@ -53,6 +53,17 @@ Type xlsxWorkBook = Class node := node.NextElement(); End; + files := zipfile_.Files(); + table_files := sselect ['FileName'] from files where AnsiContainsStr(['FileName'], 'tables/table') end; + for i:=0 to length(table_files)-1 do + begin + table_xml := GetXmlFileObj(table_files[i]); + if ifObj(table_xml) then + begin + display_name := table_xml.FirstChildElement('table').GetAttribute('displayName'); + TOfficeApi().Set('Table-' $ display_name, true); + end + end //echo tostn(sheetNames_); End; @@ -179,7 +190,7 @@ Type xlsxWorkBook = Class //设置[Content_Types].xml content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types')); - class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('SheetContentType')); + class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType')); sheetNames_[sheetsCount_]['name'] := sheet; sheetNames_[sheetsCount_]['sheetId'] := sheetId; @@ -307,11 +318,109 @@ Type xlsxWorkBook = Class End; + Function CopySheet(sourceSheet, destSheet); + Begin + ind := sheetIndexMap_[ LowerCase(destSheet) ]; + if ifint(ind) then return destSheet $ ' already exists.'; + ind := sheetIndexMap_[ LowerCase(sourceSheet) ]; + if not ifint(ind) then return sourceSheet $ ' does not exists.'; + + //copy sheet + sheetId := vselect maxof(['sheetId']) from sheetNames_ end; + sheetId := integer(sheetId) + 1; + fname := sheetPrefix_ $ inttostr(sheetsCount_ + 1) $ '.xml'; + sheet := GetSheetXmlFile(sourceSheet); + zipfile_.Add(fname, sheet.Data()); + xml_file := GetXmlFileObj(fname); + sheet_node := xml_file.FirstChildElement('worksheet').FirstChildElement('sheetviews').FirstChildElement('sheetview'); + if sheet_node.GetAttribute('tabSelected') = '1' then sheet_node.SetAttribute('tabSelected', 0); + + // sheetN.xml.rels + DrawingFun := Function(obj, target, count); + Begin + rels_name := 'xl/drawings/_rels' + ReplaceStr(target, '../drawings', '') + '.rels'; + rels_obj := GetXmlFileObj(rels_name); + rels_new_file := 'xl/drawings/_rels/drawing' $ count $ '.xml.rels'; + if ifObj(rels_obj) then + begin + zipfile_.Add(rels_new_file, rels_obj.Data()); + rels_file := GetXmlFileObj(rels_new_file); + relationship := rels_file.FirstChildElement('Relationships').FirstChildElement('Relationship'); + while ifObj(relationship) do + begin + target := relationship.GetAttribute('Target'); + if AnsiContainsStr(target, 'chart') then copyFile(relationship, target, 'chartContentType'); + relationship := relationship.NextElement(); + end + end + End; + sheet_rels := GetSheetRelsFile(sourceSheet); + if ifObj(sheet_rels) then + begin + rels_name := 'xl/worksheets/_rels/' + 'sheet' + inttostr(sheetsCount_ + 1) + '.xml.rels'; + zipfile_.Add(rels_name, sheet_rels.Data()); + rels_file := GetXmlFileObj(rels_name); + relationship := rels_file.FirstChildElement('Relationships').FirstChildElement('Relationship'); + while ifObj(relationship) do + begin + target := relationship.GetAttribute('Target'); + if AnsiContainsStr(target, 'vmlDrawing') then copyFile(relationship, target); + else if AnsiContainsStr(target, 'drawing') then + begin + [count, file] := copyFile(relationship, target, 'drawingContentType'); + ##DrawingFun(relationship, target, count); + end + else if AnsiContainsStr(target, 'comments') then copyFile(relationship, target, 'commentContentType'); + else if AnsiContainsStr(target, 'table') then + begin + [count, file] := copyFile(relationship, target, 'tableContentType'); + table_xml := GetXmlFileObj(file).FirstChildElement('table'); + table_xml.SetAttribute('id', count); + display_name := table_xml.GetAttribute('displayName'); + display_name := class(xlsxTable).GenerateValidDisplayName(display_name, count); + table_xml.SetAttribute('displayName', display_name); + end + relationship := relationship.NextElement(); + end + end + + //workbook.xml.rels + rid := getWorkbookRelsRid(); + workbook_rels := GetXmlFileObj('xl/_rels/workbook.xml.rels'); + rels := workbook_rels.FirstChildElement('Relationships').InsertEndChild('element', 'Relationship'); + rels.SetAttribute('Target', getTarget( sheetsCount_ + 1)); + rels.SetAttribute('Type', class(TSXml).GetTemplate('RelationshipWorkSheet')); + rels.SetAttribute('Id', rid); + + //xl/workbook.xml + workbook := GetXmlFileObj('xl/workbook.xml'); + node := workbook.FirstChildElement('workbook').FirstChildElement('sheets').InsertEndChild('element','sheet'); + node.SetAttribute('name', destSheet); + node.SetAttribute('sheetId', sheetId); + node.SetAttribute('r:id', rid); + + //app.xml + app := GetXmlFileObj(class(TSXml).GetFileName('docProps_app')); + vector := app.FirstChildElement('Properties').FirstChildElement('TitlesOfParts').FirstChildElement('vt:vector'); + vector.SetAttribute('size', sheetId); + vector.InsertEndChild('element', 'vt:lpstr', destSheet); + + //[Content_Types].xml + content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types')); + class(TSXml).AddOverrideContentType(content_xml, '/' + fname, class(TSXml).GetTemplate('sheetContentType')); + + sheetNames_[sheetsCount_]['name'] := destSheet; + sheetNames_[sheetsCount_]['sheetId'] := sheetId; + sheetNames_[sheetsCount_]['rid'] := rid; + sheetNames_[sheetsCount_]['file'] := fname; + sheetIndexMap_[ LowerCase(destSheet) ] := sheetsCount_; + sheetsCount_ ++; + End; + Function SetSheetName(sourceName, destName); Begin ind := sheetIndexMap_[ LowerCase(destName) ]; if ifint(ind) then return destName $ ' already exists.'; - ind := sheetIndexMap_[ LowerCase(sourceName) ]; if not ifint(ind) then return sourceName $ ' does not exists.'; @@ -1033,6 +1142,23 @@ private chart.plotAreaNode := xml.FirstChildElement(getC(chart) + 'chartSpace').FirstChildElement(getC(chart) + 'chart').FirstChildElement(getC(chart) + 'plotArea'); End; + Function copyFile(obj, target, content); + Begin + file_name := ReplaceStr(target, '..', 'xl'); + counts := GetFilesCount(ReplaceStrByReg(file_name, "\\d+.*ml", '')) + 1; + xml := GetXmlFileObj(file_name); + new_file_postfix := ReplaceStrByReg(file_name[3:], "\\d+", inttostr(counts)); + zipfile_.Add('xl' + new_file_postfix, xml.Data()); + obj.SetAttribute('Target', '..' + new_file_postfix); + + if content then + begin + content_xml := GetXmlFileObj(class(TSXml).GetFileName('Content_Types')); + class(TSXml).AddOverrideContentType(content_xml, '/xl' + new_file_postfix, class(TSXml).GetTemplate(content)); + end + return array(counts, 'xl' + new_file_postfix); + End; + sheetsCount_:integer; sheetNames_; sheetIndexMap_; diff --git a/更新日志.md b/更新日志.md index 815dea8..29b7aed 100644 --- a/更新日志.md +++ b/更新日志.md @@ -1,5 +1,19 @@ # 更新日志 +## 2023-1-16 + +### V1.1.0 + +#### word + +1. 修复页眉页脚显示问题 +2. 修复表格插入列宽失败问题 +3. 优化`InsertTable`性能 + +#### excel + +1. 新增`CopySheet` + ## 2023-1-12 ### V1.0.9