From b9e419541bad40e63440ca31d6779eb5e3a1fe2c Mon Sep 17 00:00:00 2001 From: csh Date: Wed, 20 Dec 2023 09:06:40 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84range?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docx/TSDocxApplication.tsf | 2 + docx/TSDocxCell.tsf | 12 +- docx/TSDocxCells.tsf | 6 +- docx/TSDocxColumn.tsf | 8 +- docx/TSDocxColumns.tsf | 2 + docx/TSDocxDocument.tsf | 26 +- docx/TSDocxDocuments.tsf | 8 +- docx/TSDocxEnumerations.tsf | 28 ++ docx/TSDocxParagraph.tsf | 15 +- docx/TSDocxParagraphs.tsf | 129 +++-- docx/TSDocxRange.tsf | 300 ++++++++++-- docx/TSDocxTable.tsf | 2 + docx/TSDocxTables.tsf | 26 +- docx/TSDocxTablesOfContents.tsf | 39 ++ docx/border/TSDocxBorder.tsf | 20 +- docx/border/TSDocxBorderRange.tsf | 26 +- docx/border/TSDocxBorders.tsf | 2 + docx/font/TSDocxFont.tsf | 39 +- docx/font/TSDocxFontRange.tsf | 38 +- docx/listformat/TSDocxListFormat.tsf | 114 +++++ docx/listformat/TSDocxListFormatRange.tsf | 177 +++++++ .../TSDocxParagraphFormat.tsf | 12 +- .../TSDocxParagraphFormatRange.tsf | 2 +- docx/shading/TSDocxShading.tsf | 1 + docx/shading/TSDocxShadingRange.tsf | 26 +- docx/utils/TSWdCommon.tsf | 229 --------- docx/utils/TSWdRange.tsf | 291 +++++++---- test/docx_vba_help.tsl | 461 +++++++++++++++++- utils/TSVbaBase.tsf | 6 +- 29 files changed, 1553 insertions(+), 494 deletions(-) create mode 100644 docx/TSDocxTablesOfContents.tsf create mode 100644 docx/listformat/TSDocxListFormat.tsf create mode 100644 docx/listformat/TSDocxListFormatRange.tsf rename docx/{prargraphformat => paragraphformat}/TSDocxParagraphFormat.tsf (98%) rename docx/{prargraphformat => paragraphformat}/TSDocxParagraphFormatRange.tsf (99%) delete mode 100644 docx/utils/TSWdCommon.tsf diff --git a/docx/TSDocxApplication.tsf b/docx/TSDocxApplication.tsf index d117ea1..5c20eeb 100644 --- a/docx/TSDocxApplication.tsf +++ b/docx/TSDocxApplication.tsf @@ -5,6 +5,7 @@ public Function Init(); public + // Methods Function Activate(); Function AddAddress(TagID, Value); Function AutomaticChange(); @@ -67,6 +68,7 @@ public Function SubstituteFont(UnavailableFont, SubstituteFont); Function ToggleKeyboard(); + // Properties property ActiveDocument read ReadActiveDocument; property ActiveEncryptionSession read ReadActiveEncryptionSession; property ActivePrinter read ReadActivePrinter write WriteActivePrinter; diff --git a/docx/TSDocxCell.tsf b/docx/TSDocxCell.tsf index ce2c988..0dd151e 100644 --- a/docx/TSDocxCell.tsf +++ b/docx/TSDocxCell.tsf @@ -25,8 +25,10 @@ private range_; row_; column_; + shading_; public + // Methods Function AutoSum(); Function Delete(ShiftCells); Function Formula(Formula, NumFormat); @@ -36,6 +38,7 @@ public Function SetWidth(ColumnWidth, RulerStyle); Function Split(NumRows, NumColumns); + // Properties property Borders read ReadBorders; property BottomPadding read ReadBottomPadding write WriteBottomPadding; property Column read ReadColumn; @@ -420,9 +423,12 @@ End; Function TSDocxCell.ReadShading(); Begin - shading_obj := new TSDocxShading(self.Application, self.Creator, self); - shading_obj.Init(tcpr_.Shading); - return shading_obj; + if ifnil(shading_) then + begin + shading_ := new TSDocxShading(self.Application, self.Creator, self); + shading_.Init(tcpr_.Shading); + end + return shading_; End; Function TSDocxCell.ReadBorders(index); diff --git a/docx/TSDocxCells.tsf b/docx/TSDocxCells.tsf index 848273c..8e77c74 100644 --- a/docx/TSDocxCells.tsf +++ b/docx/TSDocxCells.tsf @@ -10,6 +10,7 @@ private column_; public + // Methods Function Add(BeforeCell); Function AutoFit(); Function Delete(ShiftCells); @@ -21,6 +22,7 @@ public Function SetWidth(ColumnWidth, RulerStyle); Function Split(NumRows, NumColumns, MergeBeforeSplit); + // Properties property Borders read ReadBorders; property Count read ReadCount; property Height read ReadHeight write WriteHeight; @@ -63,12 +65,12 @@ Begin row := ifnil(row_) ? index : row_; column := ifnil(column_) ? index : column_; cell_obj := new TSDocxCell(self.Application, self.Creator, self); - cell_obj.Init(table_, row, column); + cell_obj.Init(nil, table_, row, column); return cell_obj; End; // function Function TSDocxCells.Item(Index); Begin - return self[Index - 1]; + return self[Index]; End; diff --git a/docx/TSDocxColumn.tsf b/docx/TSDocxColumn.tsf index 6f35dba..b406f32 100644 --- a/docx/TSDocxColumn.tsf +++ b/docx/TSDocxColumn.tsf @@ -13,12 +13,14 @@ private cells_; public + // Properties Function AutoFit(); Function Delete(); Function Select(); Function SetWidth(ColumnWidth, RulerStyle); Function Sort(ExcludeHeader, SortFieldType, SortOrder, CaseSensitive, BidiSort, IgnoreThe, IgnoreKashida, IgnoreDiacritics, IgnoreHe, LanguageID); + // Methods property Borders read ReadBorders; property Cells read ReadCells; property Index read ReadIndex; @@ -73,7 +75,7 @@ Begin return array(total_width, grid_col_arr); End; -// function +// Methods Function TSDocxColumn.SetWidth(ColumnWidth, RulerStyle); Begin [total_width, grid_col_arr] := SerializeTblGrid(); @@ -88,7 +90,7 @@ Begin End; -//property +// Properties Function TSDocxColumn.WriteWidth(value); Begin for i:=1 to table_.Rows() do @@ -126,5 +128,5 @@ End; Function TSDocxColumn.ReadCells(n); Begin - return ifnil(n) ? cells_: cells_[n]; + return ifnil(n) ? cells_: cells_.Item(n); End; diff --git a/docx/TSDocxColumns.tsf b/docx/TSDocxColumns.tsf index 9016cb1..49581ce 100644 --- a/docx/TSDocxColumns.tsf +++ b/docx/TSDocxColumns.tsf @@ -9,6 +9,7 @@ private table_; public + // Methods Function Add(BeforeColumn); Function AutoFit(); Function Delete(); @@ -17,6 +18,7 @@ public Function Select(); Function SetWidth(ColumnWidth, RulerStyle); + // Properties property Borders read ReadBorders; property Count read ReadCount; property First read ReadFirst; diff --git a/docx/TSDocxDocument.tsf b/docx/TSDocxDocument.tsf index 75bfb49..2d52781 100644 --- a/docx/TSDocxDocument.tsf +++ b/docx/TSDocxDocument.tsf @@ -3,6 +3,8 @@ Uses TSDocxEnumerations; public Function Init(docx, collection, name, fullname); + Function GetParam(k); + Function SetParam(k, v); private collection_; @@ -12,6 +14,8 @@ private tables_; paragraphs_; + params_; // 存一些全局参数 + public // Methods Function AcceptAllRevisions(); @@ -277,7 +281,7 @@ public property Tables read ReadTables; property TablesOfAuthorities read ReadTablesOfAuthorities write WriteTablesOfAuthorities; property TablesOfAuthoritiesCategories read ReadTablesOfAuthoritiesCategories write WriteTablesOfAuthoritiesCategories; - property TablesOfContents read ReadTablesOfContents write WriteTablesOfContents; + property TablesOfContents read ReadTablesOfContents; property TablesOfFigures read ReadTablesOfFigures write WriteTablesOfFigures; property TextEncoding read ReadTextEncoding write WriteTextEncoding; property TextLineEnding read ReadTextLineEnding write WriteTextLineEnding; @@ -336,7 +340,6 @@ public Function ReadTextEncoding(); Function WriteTablesOfFigures(); Function ReadTablesOfFigures(); - Function WriteTablesOfContents(); Function ReadTablesOfContents(); Function WriteTablesOfAuthoritiesCategories(); Function ReadTablesOfAuthoritiesCategories(); @@ -592,6 +595,18 @@ Begin tables.Init(docx_); paragraphs_ := new TSDocxParagraphs(self.Application, self.Creator, self); paragraphs_.Init(docx_); + + params_ := array(); +End; + +Function TSDocxDocument.GetParam(k); +Begin + return params_[k]; +End; + +Function TSDocxDocument.SetParam(k, v); +Begin + params_[k] := v; End; // function @@ -670,3 +685,10 @@ Function TSDocxDocument.ReadParagraphs(index); Begin return ifnil(index) ? paragraphs_ : paragraphs_.Item(index); End; + +Function TSDocxDocument.ReadTablesOfContents(); +Begin + tables_of_contents_obj := new TSDocxTablesOfContents(self.Application, self.Create, self); + tables_of_contents_obj.Init(docx_); + return tables_of_contents_obj; +End; diff --git a/docx/TSDocxDocuments.tsf b/docx/TSDocxDocuments.tsf index 279bb24..0aacc7e 100644 --- a/docx/TSDocxDocuments.tsf +++ b/docx/TSDocxDocuments.tsf @@ -12,12 +12,13 @@ private collection_; public - Function Add(Template, NewTemplate, DocumentType, Visible); // Completed + // Methods + Function Add(Template, NewTemplate, DocumentType, Visible); Function AddBlogDocument(ProviderID, PostURL, BlogName, PostID); Function CanCheckOut(FileName); Function CheckOut(FileName); Function Close(SaveChanges, OriginalFormat, RouteDocument); - Function Item(Index); // Completed + Function Item(Index); Function Open(FileName, ConfirmConversions, ReadOnly, AddToRecentFiles, PasswordDocument, PasswordTemplate, Revert, WritePasswordDocument, WritePasswordTemplate, Format, Encoding, Visible, OpenConflictDocument, OpenAndRepair, DocumentDirection, NoEncodingDialog); // Completed @@ -27,8 +28,9 @@ public DocumentDirection, NoEncodingDialog, XMLTransform); Function Save(NoPrompt, OriginalFormat); // Completed + // Properties property Count read ReadCount; - Function ReadCount(); // Completed + Function ReadCount(); End; diff --git a/docx/TSDocxEnumerations.tsf b/docx/TSDocxEnumerations.tsf index d699e85..6e019da 100644 --- a/docx/TSDocxEnumerations.tsf +++ b/docx/TSDocxEnumerations.tsf @@ -581,6 +581,14 @@ Interface Function wdWithInTable(); Function wdZoomPercentage(); + // WdCollapseDirection + Function wdCollapseEnd(); + Function wdCollapseStart(); + + // WdDefaultTableBehavior + Function wdWord8TableBehavior(); + Function wdWord9TableBehavior(); + Implementation // WdConstants enumeration @@ -2729,5 +2737,25 @@ Implementation return 19; End; + // WdCollapseDirection + Function wdCollapseEnd(); + Begin + return 0; + End; + Function wdCollapseStart(); + Begin + return 1; + End; + + // WdDefaultTableBehavior + Function wdWord8TableBehavior(); + Begin + return 0; + End; + Function wdWord9TableBehavior(); + Begin + return 1; + End; + End. diff --git a/docx/TSDocxParagraph.tsf b/docx/TSDocxParagraph.tsf index 3f8c06e..3773c90 100644 --- a/docx/TSDocxParagraph.tsf +++ b/docx/TSDocxParagraph.tsf @@ -2,11 +2,13 @@ Type TSDocxParagraph = Class(TSDocxParagraphFormat) public Function Init(docx, paragraph, index); + Function Object(); private paragraph_; // TOfficeObj("TParagraph") index_; // 第N个段落,1开始计数 range_; + document_; public // Methods @@ -23,6 +25,7 @@ public Function SelectNumber(); Function SeparateList(); + // Properties property CollapsedState read ReadCollapsedState write WriteCollapsedState; property DropCap read ReadDropCap; property Format read ReadFormat write WriteFormat; @@ -50,17 +53,25 @@ Begin index_ := index; range_ := nil; class(TSDocxParagraphFormat).Init(docx, paragraph_.pPr); + document_ := self.Parent; + while not (document_ is class(TSDocxDocument)) do + document_ := document_.Parent; +End; + +Function TSDocxParagraph.Object(); +Begin + return paragraph_; End; // Methods Function TSDocxParagraph.Next(Count); Begin - return self.Parent.Item(index + Count); + return document_.Paragraphs.Item(index_ + Count); End; Function TSDocxParagraph.Previous(Count); Begin - return self.Parent.Item(index - Count); + return document_.Paragraphs.Item(index_ - Count); End; // Properties diff --git a/docx/TSDocxParagraphs.tsf b/docx/TSDocxParagraphs.tsf index ce0eca3..72c8981 100644 --- a/docx/TSDocxParagraphs.tsf +++ b/docx/TSDocxParagraphs.tsf @@ -3,7 +3,13 @@ Type TSDocxParagraphs = Class(TSVbaBase) public Function Init(docx); Function Operator[](index); - Function SerializeParagraphs(root); + Function SerializeParagraphs(root, arr, lastNode); + Function ParseTable(root, arr, lastNode); + + Function FindNewParagraphPosition(findNode, direction); + Function AddParagraph(findNode, newNode, direction); + Function AddTableToParagraphs(findNode, tTable); + Function DeleteParagraph(findNode); private docx_; @@ -11,6 +17,7 @@ private paragraphs_; // TOfficeObj("TParagraph")数组 public + // Methods Function Add(Range); Function CloseUp(); Function DecreaseSpacing(); @@ -32,6 +39,7 @@ public Function TabHangingIndent(Count); Function TabIndent(Count); + // Properties property AddSpaceBetweenFarEastAndAlpha read ReadAddSpaceBetweenFarEastAndAlpha write WriteAddSpaceBetweenFarEastAndAlpha; property AddSpaceBetweenFarEastAndDigit read ReadAddSpaceBetweenFarEastAndDigit write WriteAddSpaceBetweenFarEastAndDigit; property Alignment read ReadAlignment write WriteAlignment; @@ -156,10 +164,10 @@ Begin docx_ := docx; paragraphs_ := array(); lastnode_ := nil; - SerializeParagraphs(docx_.Body().Node()); + self.SerializeParagraphs(docx_.Body().Node(), paragraphs_, lastnode_); End; -Function TSDocxParagraphs.SerializeParagraphs(root); +Function TSDocxParagraphs.SerializeParagraphs(root, arr, lastNode); Begin node := root.FirstChildElement(); while ifObj(node) do @@ -169,53 +177,116 @@ Begin begin obj := TOfficeObj("TParagraph"); obj.Init(node); - paragraphs_[length(paragraphs_)] := obj; - lastnode_ := node; + arr[length(arr)] := obj; + lastNode := node; end else if name = "w:tbl" then begin - tr := node.FirstChildElement("w:tr"); - while ifObj(tr) do - begin - tc := tr.FirstChildElement("w:tc"); - while ifObj(tc) do - begin - SerializeParagraphs(tc); - tc := tc.NextElement("w:tc"); - end - paragraphs_[length(paragraphs_)] := TOfficeObj("TParagraph"); - tr := tr.NextElement("w:tr"); - end - lastnode_ := node; + self.ParseTable(node, arr, lastNode); + lastNode := node; end node := node.NextElement(); End; End; +Function TSDocxParagraphs.ParseTable(root, arr, lastNode); +Begin + tr := root.FirstChildElement("w:tr"); + while ifObj(tr) do + begin + tc := tr.FirstChildElement("w:tc"); + while ifObj(tc) do + begin + SerializeParagraphs(tc, arr, lastNode); + tc := tc.NextElement("w:tc"); + end + arr[length(arr)] := TOfficeObj("TParagraph"); + tr := tr.NextElement("w:tr"); + end +End; + +Function TSDocxParagraphs.FindNewParagraphPosition(findNode, direction); +Begin + pos := length(paragraphs_); + for i:=0 to length(paragraphs_)-1 do + begin + if not ifObj(paragraphs_[i].Root()) then continue; + if paragraphs_[i].Root().Eq(findNode) then + begin + pos := direction = "after" ? i + 1 : i; + break; + end + end + return pos; +End; + +Function TSDocxParagraphs.AddParagraph(findNode, newNode, direction); +Begin + pos := self.FindNewParagraphPosition(findNode, direction); + if pos = length(paragraphs_) then lastnode_ := newNode; + for i:=length(paragraphs_) downto pos do + paragraphs_[i] := paragraphs_[i-1]; + obj := TOfficeObj("TParagraph"); + obj.Init(newNode); + paragraphs_[pos] := obj; + return pos; +End; + +Function TSDocxParagraphs.AddTableToParagraphs(findNode, tTable); +Begin + pos := self.FindNewParagraphPosition(findNode, "after"); + // 序列化表格为段落 + node := tTable.Root(); + if pos = length(paragraphs_) then lastnode_ := node; + arr := array(); + last_node := nil; + self.ParseTable(node, arr, last_node); + len := length(arr); + for i:=length(paragraphs_)-1 downto pos do + paragraphs_[i+len] := paragraphs_[i]; + for i:=pos to pos + len - 1 do + paragraphs_[i] := arr[i-pos]; +End; + +Function TSDocxParagraphs.DeleteParagraph(findNode); +Begin + pos := self.FindNewParagraphPosition(findNode, "before"); + if ifObj(findNode) then findNode.Parent().DeleteChild(findNode); + for i:=pos to length(paragraphs_)-2 do + paragraphs_[i] := paragraphs_[i+1]; + reindex(paragraphs_, array(length(paragraphs_)-1 : nil)); +End; + Function Operator TSDocxParagraphs.[](index); Begin paragraph_obj := new TSDocxParagraph(self.Application, self.Creator, self.Parent); - paragraph_obj.Init(docx_, paragraphs_[index], index + 1); + paragraph_obj.Init(docx_, paragraphs_[index - 1], index); return paragraph_obj; End; // Methods Function TSDocxParagraphs.Add(Range); Begin - if lastnode_ then - node := docx_.Body().Root().InsertAfterChild(lastnode_, "element", "w:p"); - else - node := docx_.Body().Root().InsertFirstChild("element", "w:p"); - lastnode_ := node; - obj := TOfficeObj("TParagraph"); - obj.Init(node); - paragraphs_[length(paragraphs_)] := obj; - return self.Item(length(paragraphs_) - 1); + if Range is Class(TSDocxRange) then + begin + Range.AddParagraph(); + end + else begin + if lastnode_ then + node := docx_.Body().Root().InsertAfterChild(lastnode_, "element", "w:p"); + else + node := docx_.Body().Root().InsertEndChild("element", "w:p"); + lastnode_ := node; + obj := TOfficeObj("TParagraph"); + obj.Init(node); + paragraphs_[length(paragraphs_)] := obj; + return self.Item(length(paragraphs_) - 1); + end End; Function TSDocxParagraphs.Item(Index); Begin - return self[Index - 1]; + return self[Index]; End; Function TSDocxParagraphs.ReadCount(); diff --git a/docx/TSDocxRange.tsf b/docx/TSDocxRange.tsf index 7973f60..38cd594 100644 --- a/docx/TSDocxRange.tsf +++ b/docx/TSDocxRange.tsf @@ -3,16 +3,28 @@ Uses TSDocxEnumerations; public Function Init(docx, rangeObj); + Function AddParagraph();overload; + Function AddParagraph(direction);overload; + Function AddTable(numRows, numColumns); + Function Clear(deleteAll); + Function InsertPara(); + +private Function CopyRunFormat(sourceRun, destRun); + Function BreakIntoParagraphs(direction); private docx_; range_obj_; // TSWdRange range_font_; // TSDocxFontRange paragraph_format_range_; // TSDocxParagraphFormatRange + list_format_range_; // TSDocxListFormatRange borders_range_; // TSDocxBordersRange + document_; // TSDocxDocument + collapse_; public + // Methods Function AutoFormat(); Function Calculate(); Function CheckGrammar(); @@ -90,6 +102,7 @@ public Function TCSCConverter(WdTCSCConverterDirection, CommonTerms, UseVariants); Function WholeStory(); + // Properties property Bold read ReadBold write WriteBold; property BoldBi read ReadBoldBi write WriteBoldBi; property BookmarkID read ReadBookmarkID; @@ -117,7 +130,7 @@ public property Fields read ReadFields; property Find read ReadFind; property FitTextWidth read ReadFitTextWidth write WriteFitTextWidth; - property Font read ReadFont; + property Font read ReadFont write WriteFont; property FootnoteOptions read ReadFootnoteOptions; property Footnotes read ReadFootnotes; property FormattedText read ReadFormattedText write WriteFormattedText; @@ -271,6 +284,7 @@ public Function ReadFormattedText(); Function ReadFootnotes(); Function ReadFootnoteOptions(); + Function WriteFont(value); Function ReadFont(); Function WriteFitTextWidth(value); Function ReadFitTextWidth(); @@ -320,8 +334,107 @@ Begin range_font_.Init(range_obj_); paragraph_format_range_ := new TSDocxParagraphFormatRange(self.Application, self.Creator, self); paragraph_format_range_.Init(docx_, range_obj_); + list_format_range_ := new TSDocxListFormatRange(self.Application, self.Creator, self); + list_format_range_.Init(docx_, range_obj_); borders_range_ := new TSDocxBordersRange(self.Application, self.Creator, self); borders_range_.Init(range_obj_); + collapse_ := nil; + document_ := self.Parent; + while not (document_ is class(TSDocxDocument)) do + document_ := document_.Parent; +End; + +Function TSDocxRange.AddParagraph();overload; +Begin + if collapse_ = TSDocxEnumerations.wdCollapseEnd() then + return self.AddParagraph("after"); + return self.AddParagraph("before"); +End; + +Function TSDocxRange.AddParagraph(direction);overload; +Begin + [flag, last_node, new_node] := self.BreakIntoParagraphs(direction); + if not flag then + new_node := direction = "before" ? last_node.Parent().InsertBeforeChild(last_node, "element", "w:p") + : last_node.Parent().InsertAfterChild(last_node, "element", "w:p"); + pos := document_.Paragraphs.AddParagraph(last_node, new_node, direction); + return document_.Paragraphs.Item(pos + 1); +End; + +Function TSDocxRange.InsertPara(); +Begin + case collapse_ of + TSDocxEnumerations.wdCollapseStart(): + return self.AddParagraph("before"); + + TSDocxEnumerations.wdCollapseEnd(): + return self.AddParagraph("after"); + + else begin + self.Clear(); + if not range_obj_[0].TParagraph.Empty() then return self.AddParagraph("after"); + pos := document_.Paragraphs.FindNewParagraphPosition(range_obj_[0].TParagraph.Root()); + return document_.Paragraphs.Item(pos + 1); + end + end; +End; + +Function TSDocxRange.AddTable(numRows, numColumns); +Begin + padd_table := function(ttable, node); + begin + if node.Parent().GetName() = "w:tc" then + begin + docx := new TCell(); + docx.Create(node); + table := docx.InsertTable(ttable, node); + end + else if node.Parent().GetName() = "w:body" then + begin + table := docx_.InsertTable(ttable, node); + end + return table; + end + + psplit := function(direction); + begin + [flag, last_node, new_node] := self.BreakIntoParagraphs(direction); + if flag then + begin + document_.Paragraphs.AddParagraph(last_node, new_node, direction); + end + else begin + index := direction = "before" ? 0 : range_obj_.Size()-1; + new_node := range_obj_[index].TParagraph.Root(); + end + return new_node; + end + + case collapse_ of + TSDocxEnumerations.wdCollapseStart(): + new_node := ##psplit("before"); + + TSDocxEnumerations.wdCollapseEnd(): + new_node := ##psplit("after"); + + else begin + new_node := range_obj_[range_obj_.Size()-1].TParagraph.Root(); + clear_flag := true; + end + end; + data := nils(numRows, numColumns); + ttable := docx_.CreateTable(data); + table := ##padd_table(ttable, new_node); + document_.Paragraphs.AddTableToParagraphs(new_node, table); + if clear_flag then self.Clear(true); + return table; +End; + +Function TSDocxRange.Clear(deleteAll); +Begin + arr := range_obj_.Clear(deleteAll); + for i:=0 to length(arr)-1 do + document_.Paragraphs.DeleteParagraph(arr[i]); End; Function TSDocxRange.CopyRunFormat(sourceRun, destRun); @@ -332,11 +445,53 @@ Begin class(TSXml).UpdateNode(node, marshal[0]["attribute"], marshal[0]["children"]); End; -// Methods -// TODO -Function TSDocxRange.InsertAfter(Text); +Function TSDocxRange.BreakIntoParagraphs(direction); Begin - paragraph := range_arr_[length(range_arr_)-1]["tparagraph"]; + index := direction = "before" ? 0 : range_obj_.Size()-1; + range_obj_.SplitRun(index); + run := range_obj_[index].TRun; + paragraph := range_obj_[index].TParagraph; + root := paragraph.Root(); + + if not ifObj(run.Root()) or + (not run.Root().NextElement("w:r") and direction = "after") or + (not run.Root().PrevElement("w:r") and direction = "before") + then return array(false, root, nil); + + parent_node := root.Parent(); + node := direction = "before" ? parent_node.InsertBeforeChild(root, "element", "w:p") : parent_node.InsertAfterChild(root, "element", "w:p"); + ppr := root.FirstChildElement("w:pPr"); + ppr_node := ppr ? node.InsertFirstChild(string(ppr.Data())) : node.InsertFirstChild("element", "w:rPr"); + + if direction = "before" then + begin + run_node := root.FirstChildElement("w:r"); + while not run_node.Eq(run.Root()) do + begin + node.InsertEndChild(string(run_node.Data())); + delete_node := run_node; + run_node := run_node.NextElement("w:r"); + root.DeleteChild(delete_node); + end + end + else begin + run_node := run.Root().NextElement("w:r"); + while ifObj(run_node) do + begin + node.InsertEndChild(string(run_node.Data())); + delete_node := run_node; + run_node := run_node.NextElement("w:r"); + root.DeleteChild(delete_node); + end + end + return array(true, root, node); +End; + +// Methods +Function TSDocxRange.InsertAfter(Text); // 无论range是什么,都在段落末尾添加文字 +Begin + size := range_obj_.Size(); + paragraph := range_obj_[size-1].TParagraph; if paragraph.Empty() then begin run := paragraph.AppendRun(); @@ -344,17 +499,17 @@ Begin paragraph.CopyRunFormat(false, run.Root()); end else begin - trun := range_arr_[length(range_arr_)-1]["trun"]; + trun := range_obj_[size-1].TRun; run := paragraph.AppendRun(trun); run.AddText(Text); - CopyRunFormat(trun.Root(), run.Root()); + self.CopyRunFormat(trun.Root(), run.Root()); end + range_obj_.Refresh(); End; -// TODO -Function TSDocxRange.InsertBefore(Text); +Function TSDocxRange.InsertBefore(Text); // 无论range是什么,都在段落前添加文字 Begin - paragraph := range_arr_[0]["tparagraph"]; + paragraph := range_obj_[0].TParagraph; if paragraph.Empty() then begin run := paragraph.AppendRun(); @@ -362,31 +517,51 @@ Begin paragraph.CopyRunFormat(false, run.Root()); end else begin - trun := range_arr_[0]["trun"]; - node := trun.Root().PrevElement(); - if not ifObj(node) then node := trun.Root(); + trun := range_obj_[0].TRun; run := paragraph.PrependRun(trun); run.AddText(Text); - CopyRunFormat(node, run.Root()); + self.CopyRunFormat(trun.Root(), run.Root()); end + range_obj_.Refresh(); End; -// TODO Function TSDocxRange.InsertBreak(Type); Begin + if self.Information(TSDocxEnumerations.wdWithInTable()) then + raise "This method is not supported for the table range and cell range"; pf := function(t, c); begin - range_arr_[0] := class(TSWdCommon).SplitSingleRangeRun(range_arr_[0]); - run := range_arr_[0]["trun"]; + case collapse_ of + TSDocxEnumerations.wdCollapseStart(): + index := 0; + + TSDocxEnumerations.wdCollapseEnd(): + index := range_obj_.Size()-1; + + else begin + range_obj_.Clear(); + index := 0; + end + end; + range_obj_.SplitRun(index); + tparagraph := range_obj_[index].TParagraph; + run := tparagraph.PrependRun(range_obj_[index].TRun); run.Br.Type := t; run.Br.Clear := c; - run.ClearText(); run.Apply(); end + if ifnil(Type) then Type := TSDocxEnumerations.wdPageBreak(); case Type of TSDocxEnumerations.wdColumnBreak(): - return; + begin + paragraph_obj := self.InsertPara(); + if collapse_ = TSDocxEnumerations.wdCollapseStart() then paragraph_obj := paragraph_obj.Next(1); + obj := paragraph_obj.Object(); + run := obj.PrependRun(); + run.Br.Type := "column"; + run.Apply(); + end TSDocxEnumerations.wdLineBreak(): ##pf("textWrapping", nil); @@ -397,23 +572,57 @@ Begin TSDocxEnumerations.wdLineBreakClearRight(): ##pf("textWrapping", "right"); - TSDocxEnumerations.wdPageBreak(): // TODO:需要切割段落 - return; - TSDocxEnumerations.wdSectionBreakContinuous(): - return; - TSDocxEnumerations.wdSectionBreakEvenPage(): - return; - TSDocxEnumerations.wdSectionBreakNextPage(): - return; + TSDocxEnumerations.wdPageBreak(): + begin + paragraph_obj := self.InsertPara(); + paragraph_obj := self.InsertPara(); + paragraph_obj.Format.Alignment := TSDocxEnumerations.wdAlignParagraphLeft(); + paragraph_obj.Format.WidowControl := true; + paragraph_obj.Format.Apply(); + obj := paragraph_obj.Object(); + run := obj.AppendRun(); + run.Br.Type := "page"; + run.Apply(); + end + + TSDocxEnumerations.wdSectionBreakContinuous(), + TSDocxEnumerations.wdSectionBreakEvenPage(), + TSDocxEnumerations.wdSectionBreakNextPage(), TSDocxEnumerations.wdSectionBreakOddPage(): - return; + raise "This Type is not suppoted"; TSDocxEnumerations.wdTextWrappingBreak(): ##pf("textWrapping", "all"); end; End; -// property +Function TSDocxRange.Collapse(Direction); +Begin + if ifnil(Direction) then Direction := TSDocxEnumerations.wdCollapseStart(); + collapse_ := Direction; +End; + +Function TSDocxRange.Delete(_Unit, Count); +Begin + self.Clear(true); +End; + +Function TSDocxRange.InsertParagraph(); +Begin + self.InsertPara(); +End; + +Function TSDocxRange.InsertParagraphAfter(); +Begin + self.AddParagraph("after"); +End; + +Function TSDocxRange.InsertParagraphBefore(); +Begin + self.AddParagraph("before"); +End; + +// Properties Function TSDocxRange.WriteBoldBi(value); Begin range_font_.BoldBi := value; @@ -431,6 +640,11 @@ Begin return range_font_.Bold; End; +Function TSDocxRange.WriteFont(value); +Begin + range_font_.ReWrite(value); +End; + Function TSDocxRange.ReadFont(); Begin return range_font_; @@ -495,14 +709,15 @@ Begin // TSDocxEnumerations.wdVerticalPositionRelativeToTextBoundary(): TSDocxEnumerations.wdWithInTable(): begin - for i:=0 to length(range_arr_) do + for i:=0 to range_obj_.Size()-1 do begin - node := range_arr_[i]["parent"]; - if node.GetName() <> "w:tbl" then return false; + node := range_obj_[i].TParagraph.Root(); + if not (node.Parent().GetName() in array("w:tbl", "w:tc")) then return false; end return true; end // TSDocxEnumerations.wdZoomPercentage(): + else raise "This Type is not suppoted"; end; End; @@ -517,23 +732,28 @@ End; Function TSDocxRange.WriteText(value); Begin - range_obj_.Clear(); - run := range_obj_.Data[0]["trun"]; + self.Clear(); + run := range_obj_[0].TRun; if ifObj(run.Root()) then run.SetText(value); else begin - run := range_obj_.Data[0]["tparagraph"].AppendRun(); + run := range_obj_[0].TParagraph.AppendRun(); run.SetText(value); - range_obj_.Data[0]["trun"] := run; + range_obj_[0].TRun := run; end End; Function TSDocxRange.ReadText(); Begin txt := ""; - prev := range_obj_.Data[0]["tparagraph"]; - for i:=0 to length(range_obj_.Data)-1 do + prev := range_obj_[0].TParagraph; + for i:=0 to range_obj_.Size()-1 do begin - run := range_obj_.Data[i]["trun"]; - txt += prev = range_obj_.Data[i]["tparagraph"] ? run.Text() : "\n" + run.Text(); + run := range_obj_[i].TRun; + txt += prev = range_obj_[i].TParagraph ? run.Text() : "\n" + run.Text(); end return txt; End; + +Function TSDocxRange.ReadListFormat(); +Begin + return list_format_range_; +End; diff --git a/docx/TSDocxTable.tsf b/docx/TSDocxTable.tsf index 635b25d..9da9ae5 100644 --- a/docx/TSDocxTable.tsf +++ b/docx/TSDocxTable.tsf @@ -10,6 +10,7 @@ private range_; public + // Methods Function ApplyStyleDirectFormatting(StyleName); Function AutoFitBehavior(Behavior); Function AutoFormat(Format, ApplyBorders, ApplyShading, ApplyFont, ApplyColor, ApplyHeadingRows, ApplyLastRow, ApplyFirstColumn, ApplyLastColumn, AutoFit); @@ -23,6 +24,7 @@ public Function Split(BeforeRow); Function UpdateAutoFormat(); + // Properties property AllowAutoFit read ReadAllowAutoFit write WriteAllowAutoFit; property ApplyStyleColumnBands read ReadApplyStyleColumnBands write WriteApplyStyleColumnBands; property ApplyStyleFirstColumn read ReadApplyStyleFirstColumn write WriteApplyStyleFirstColumn; diff --git a/docx/TSDocxTables.tsf b/docx/TSDocxTables.tsf index f34c58d..50486a4 100644 --- a/docx/TSDocxTables.tsf +++ b/docx/TSDocxTables.tsf @@ -1,4 +1,5 @@ Type TSDocxTables = Class(TSVbaBase) +Uses TSDocxEnumerations; public Function Init(docx); @@ -8,9 +9,11 @@ private docx_; public + // Methods Function Add(Range, NumRows, NumColumns, DefaultTableBehavior, AutoFitBehavior); Function Item(Index); + // Properties property Count read ReadCount; property NestingLevel read ReadNestingLevel; Function ReadNestingLevel(); @@ -32,14 +35,33 @@ Begin return table_obj; End; -// function +// Methods +Function TSDocxTables.Add(Range, NumRows, NumColumns, DefaultTableBehavior, AutoFitBehavior); +Begin + table := Range.AddTable(NumRows, NumColumns); + table_obj := new TSDocxTable(self.Application, self.Creator, self); + table_obj.Init(docx_, table); + if ifnil(DefaultTableBehavior) then DefaultTableBehavior := TSDocxEnumerations.wdWord8TableBehavior(); + if DefaultTableBehavior = TSDocxEnumerations.wdWord8TableBehavior() then + begin + root := table.Root(); + tplpr := root.FirstChildElement("w:tblPr"); + style := tplpr.FirstChildElement("w:tblStyle"); + if style then tplpr.DeleteChild(style); + end + if ifnil(AutoFitBehavior) then AutoFitBehavior := TSDocxEnumerations.wdAutoFitContent(); + table_obj.AutoFitBehavior(AutoFitBehavior); + return table_obj; +End; + Function TSDocxTables.Item(Index); Begin return self[Index]; End; -// property +// Properties Function TSDocxTables.ReadCount(); Begin return docx_.TablesCount(); End; + diff --git a/docx/TSDocxTablesOfContents.tsf b/docx/TSDocxTablesOfContents.tsf new file mode 100644 index 0000000..4eecead --- /dev/null +++ b/docx/TSDocxTablesOfContents.tsf @@ -0,0 +1,39 @@ +Type TSDocxTablesOfContents = Class(TSVbaBase) + +public + Function Init(docx); + +public + // Methods + Function Add(Range, UseHeadingStyles, UpperHeadingLevel, LowerHeadingLevel, UseFields, TableID, RightAlignPageNumbers, IncludePageNumbers, AddedStyles, UseHyperlinks, HidePageNumbersInWeb, UseOutlineLevels); + Function Item(Index); + Function MarkEntry(Range, Entry, EntryAutoText, TableID, Level); + + // Properties + property Count read ReadCount; + property Format read ReadFormat write WriteFormat; + Function WriteFormat(value); + Function ReadFormat(); + Function ReadCount(); + +private + docx_; + +End; + +// ============== 实现 ================= // +Function TSDocxTablesOfContents.Init(docx); +Begin + docx_ := docx; +End; + + +// Methods +Function TSDocxTablesOfContents.Add(Range, UseHeadingStyles, UpperHeadingLevel, LowerHeadingLevel, UseFields, TableID, RightAlignPageNumbers, IncludePageNumbers, AddedStyles, UseHyperlinks, HidePageNumbersInWeb, UseOutlineLevels); +Begin + paragraph := Range.InsertPara(); + if ifnil(UpperHeadingLevel) then UpperHeadingLevel := 1; + if ifnil(LowerHeadingLevel) then LowerHeadingLevel := 9; + docx_.AddTableContent(paragraph.Object(), UpperHeadingLevel, LowerHeadingLevel); + paragraph.Range.Clear(True); +End; diff --git a/docx/border/TSDocxBorder.tsf b/docx/border/TSDocxBorder.tsf index d39a0a3..ff6dc53 100644 --- a/docx/border/TSDocxBorder.tsf +++ b/docx/border/TSDocxBorder.tsf @@ -3,6 +3,7 @@ Uses TSDocxEnumerations; public Function Init(borders); + Function Apply();virtual; protected border_; @@ -10,6 +11,7 @@ protected color_index_; public + // Properties property ArtStyle read ReadArtStyle write WriteArtStyle; property ArtWidth read ReadArtWidth write WriteArtWidth; property Color read ReadColor write WriteColor; @@ -45,6 +47,11 @@ Begin color_ := TSWdColor(); End; +Function TSDocxBorder.Apply();virtual; +Begin + border_.Update("first"); +End + // property Function TSDocxBorder.WriteArtStyle(value);virtual; Begin @@ -215,7 +222,6 @@ Begin // TSDocxEnumerations.wdArtZigZag(): // TSDocxEnumerations.wdArtZigZagStitch(): end; - border_.Update("first"); End; Function TSDocxBorder.ReadArtStyle();virtual; Begin @@ -228,7 +234,6 @@ End; Function TSDocxBorder.WriteArtWidth(value);virtual; Begin border_.Size := value; - border_.Update("first"); End; Function TSDocxBorder.ReadArtWidth();virtual; Begin @@ -238,7 +243,6 @@ End; Function TSDocxBorder.WriteColor(value);virtual; Begin border_.Color := color_[value]; - border_.Update("first"); End; Function TSDocxBorder.ReadColor();virtual; Begin @@ -247,11 +251,10 @@ End; Function TSDocxBorder.WriteColorIndex(value);virtual; Begin - color := color_index_[value]; - if ifnil(color) then border_.Root().DeleteAttribute("w:color"); + color_index := color_index_[value]; + if ifnil(color_index) then border_.Root().DeleteAttribute("w:color"); else begin - border_.Color := color; - border_.Update("first"); + border_.Color := color_index; end End; Function TSDocxBorder.ReadColorIndex();virtual; @@ -338,7 +341,6 @@ Begin border_.Val := "triple"; end; - border_.Update("first"); End; @@ -426,7 +428,6 @@ End; Function TSDocxBorder.WriteLineWidth(value);virtual; Begin border_.Size := value; - border_.Update("first"); End; Function TSDocxBorder.ReadLineWidth();virtual; Begin @@ -436,7 +437,6 @@ End; Function TSDocxBorder.WriteVisible(value);virtual; Begin v := value ? "single" : "nil"; - border_.Update("first"); End; Function TSDocxBorder.ReadVisible();virtual; Begin diff --git a/docx/border/TSDocxBorderRange.tsf b/docx/border/TSDocxBorderRange.tsf index ac47419..674aba9 100644 --- a/docx/border/TSDocxBorderRange.tsf +++ b/docx/border/TSDocxBorderRange.tsf @@ -3,6 +3,7 @@ Uses TSDocxEnumerations; public Function Init(rangeObj, borderType); + Function Apply();override; private Function GetBorderObjectByNode(node); @@ -42,6 +43,11 @@ Begin class(TSDocxBorder).Init(nil); End; +Function TSDocxBorderRange.Apply();override; +Begin + CallFunction(ThisFunction(class(TSDocxBorder).Apply)); +End; + Function TSDocxBorderRange.SplitRun(); Begin range_obj_.SplitRangeRun(); @@ -50,14 +56,14 @@ End; Function TSDocxBorderRange.GetBorder(arr, hash); Begin - if arr["entirety"] then + if arr.Entirety then begin - if not ifnil(hash[arr["entirety"]]) then nil; - hash[arr["entirety"]] := true; - border := GetBorderObjectByNode(arr["entirety"]); + if not ifnil(hash[arr.Entirety]) then nil; + hash[arr.Entirety] := true; + border := GetBorderObjectByNode(arr.Entirety); end else begin - trun := arr["trun"]; + trun := arr.TRun; if not ifObj(trun.Root()) then return nil; border := new TSDocxBorder(self.Application, self.Creator, self.Parent); border.Init(trun.rPr.Bdr); @@ -96,10 +102,9 @@ Function TSDocxBorderRange.CallFunction(fname, value);overload; Begin SplitRun(); hash := array(); - range_arr := rangeObj.GetInfo(); - for i:=0 to length(range_arr)-1 do + for i:=0 to range_obj_.Size()-1 do begin - border := GetBorder(range_arr[i], hash); + border := GetBorder(range_obj_[i], hash); if ifnil(border) then continue; pf := FindFunction(fname, border); pf.Do(value); @@ -109,11 +114,10 @@ End; Function TSDocxBorderRange.CallFunction(fname);overload; Begin hash := array(); - range_arr := rangeObj.GetInfo(); ret := nil; - for i:=0 to length(range_arr)-1 do + for i:=0 to range_obj_.Size()-1 do begin - border := GetBorder(range_arr[i], hash); + border := GetBorder(range_obj_[i], hash); if ifnil(border) then continue; pf := FindFunction(fname, border); r := pf.Do(); diff --git a/docx/border/TSDocxBorders.tsf b/docx/border/TSDocxBorders.tsf index e1f03f2..9787666 100644 --- a/docx/border/TSDocxBorders.tsf +++ b/docx/border/TSDocxBorders.tsf @@ -5,9 +5,11 @@ public Function GetBorder(index);virtual; public + // Methods Function ApplyPageBordersToAllSections(); Function Item(Index);virtual; + // Properties property AlwaysInFront read ReadAlwaysInFront write WriteAlwaysInFront; property Count read ReadCount; property DistanceFrom read ReadDistanceFrom write WriteDistanceFrom; diff --git a/docx/font/TSDocxFont.tsf b/docx/font/TSDocxFont.tsf index 72b2afd..c7acd92 100644 --- a/docx/font/TSDocxFont.tsf +++ b/docx/font/TSDocxFont.tsf @@ -4,6 +4,7 @@ Uses TSDocxEnumerations; public Function Init(pr); Function Apply();virtual; + Function ReWrite(pr);virtual; protected pr_; @@ -11,15 +12,18 @@ protected color_; public + // Methods Function Grow();virtual; Function Reset();virtual; Function SetAsTemplateDefault();virtual; Function Shrink();virtual; + // Properties property AllCaps read ReadAllCaps write WriteAllCaps; property Bold read ReadBold write WriteBold; property BoldBi read ReadBoldBi write WriteBoldBi; property Borders read ReadBorders; + property Color read ReadColor write WriteColor; property ColorIndex read ReadColorIndex write WriteColorIndex; property ColorIndexBi read ReadColorIndexBi write WriteColorIndexBi; property ContextualAlternates read ReadContextualAlternates write WriteContextualAlternates; @@ -144,6 +148,8 @@ public Function ReadColorIndexBi();virtual; Function WriteColorIndex(value);virtual; Function ReadColorIndex();virtual; + Function WriteColor(value);virtual; + Function ReadColor();virtual; Function ReadBorders();virtual; Function WriteBoldBi(value);virtual; Function ReadBoldBi();virtual; @@ -167,6 +173,16 @@ Begin pr_.Update("first"); End; +Function TSDocxFont.ReWrite(pr);virtual; +Begin + self.Reset(); + rpr := pr.Root().FirstChildElement("w:rPr"); + if not ifObj(rpr) then return; + marshal := rPr.Marshal()[0]; + node := class(TSXml).GetNode(pr_.Root(), "w:rPr", "first"); + class(TSXml).UpdateNode(node, marshal["attributes"], marshal["children"]); +End; + // Methods Function TSDocxFont.Reset();virtual; Begin @@ -201,13 +217,23 @@ Begin return pr_.Value("bCs"); End; +Function TSDocxFont.WriteColor(value);virtual; +Begin + val := color_index_[value]; + if ifnil(val) then val := color_[value]; + pr_.Color := val; +End; +Function TSDocxFont.ReadColor();virtual; +Begin + v := pr.Value("Color"); + value := color_index_[v]; + if ifnil(value) then return color_[v]; +End; + Function TSDocxFont.WriteColorIndex(value);virtual; Begin - color := color_index_[value]; - if ifnil(color) then pr_.Root().DeleteChild("w:color"); - else begin - pr_.Color := color; - end + val := color_index_[value]; + pr_.Color := val; End; Function TSDocxFont.ReadColorIndex();virtual; Begin @@ -283,7 +309,7 @@ End; Function TSDocxFont.ReadEmphasisMark();virtual; Begin case pr_.Value("first") of - "none": + "none", nil: return TSDocxEnumerations.wdEmphasisMarkNone; "comma": return TSDocxEnumerations.wdEmphasisMarkOverComma; @@ -701,3 +727,4 @@ Function TSDocxFont.ReadUnderlineColor();virtual; Begin return color_[pr_.Value("UColor")]; End; + diff --git a/docx/font/TSDocxFontRange.tsf b/docx/font/TSDocxFontRange.tsf index 7728608..7e1580e 100644 --- a/docx/font/TSDocxFontRange.tsf +++ b/docx/font/TSDocxFontRange.tsf @@ -4,6 +4,7 @@ Uses TSDocxEnumerations; public Function Init(rangeObj); Function Apply();overload; + Function ReWrite(pr);override; private Function CallFunction(pf, value);overload; @@ -11,7 +12,6 @@ private private range_obj_; - split_flag_; // 写之前切割run,切割后设为true public Function Reset();override; @@ -96,6 +96,8 @@ public Function ReadColorIndexBi();override; Function WriteColorIndex(value);override; Function ReadColorIndex();override; + Function WriteColor(value);override; + Function ReadColor();override; Function ReadBorders();override; Function WriteBoldBi(value);override; Function ReadBoldBi();override; @@ -118,30 +120,29 @@ Begin CallFunction(ThisFunction(class(TSDocxFont).Apply)); End; +Function TSDocxFontRange.ReWrite(pr);override; +Begin + CallFunction(ThisFunction(class(TSDocxFont).ReWrite), pr); +End; + Function TSDocxFontRange.CallFunction(pf, value);overload; Begin range_obj_.SplitRun(); - range_arr := range_obj_.GetInfo(); - for i:=0 to length(range_arr)-1 do + for i:=0 to range_obj_.Size()-1 do begin - paragraph := range_arr[i]["tparagraph"]; - pr_ := paragraph.pPr.rPr; + pr_ := range_obj_[i].TParagraph.pPr.rPr; + ##pf(value); + pr_ := range_obj_[i].TRun.rPr; ##pf(value); - for i:=0 to length(range_arr)-1 do - begin - pr_ := range_arr[i]["trun"].rPr; - ##pf(value); - end end; End; Function TSDocxFontRange.CallFunction(pf);overload; Begin ret := nil; - range_arr := range_obj_.GetInfo(); - for i:=0 to length(range_arr)-1 do + for i:=0 to range_obj_.Size()-1 do begin - pr_ := range_arr[i]["trun"].rPr; + pr_ := range_obj_[i].TRun.rPr; if not ifObj(pr_.Root()) then continue; cur := ##pf(); if ifnil(ret) then ret := cur; @@ -509,13 +510,22 @@ End; Function TSDocxFontRange.WriteColorIndex(value);override; Begin - return CallFunction(ThisFunction(class(TSDocxFont).WriteColorIndex), value); + CallFunction(ThisFunction(class(TSDocxFont).WriteColorIndex), value); End; Function TSDocxFontRange.ReadColorIndex();override; Begin return CallFunction(ThisFunction(class(TSDocxFont).ReadColorIndex)); End; +Function TSDocxFontRange.WriteColor(value);override; +Begin + CallFunction(ThisFunction(class(TSDocxFont).WriteColor), value); +End; +Function TSDocxFontRange.ReadColor();override; +Begin + return CallFunction(ThisFunction(class(TSDocxFont).ReadColor)); +End; + Function TSDocxFontRange.ReadBorders();override; Begin return CallFunction(ThisFunction(class(TSDocxFont).ReadBorders)); diff --git a/docx/listformat/TSDocxListFormat.tsf b/docx/listformat/TSDocxListFormat.tsf new file mode 100644 index 0000000..cf9958f --- /dev/null +++ b/docx/listformat/TSDocxListFormat.tsf @@ -0,0 +1,114 @@ +Type TSDocxListFormat = Class(TSVbaBase) +Uses TSDocxEnumerations; + +public + Function Init(docx, pPr); + Function Apply();virtual; + Function GetNumId(type); + +protected + docx_; + pr_; // TOfficeObj("TwpPr") + document_; + +public + // Methods + Function ApplyBulletDefault(DefaultListBehavior);virtual; + Function ApplyListTemplate(ListTemplate, ContinuePreviousList, ApplyTo, DefaultListBehavior);virtual; + Function ApplyListTemplateWithLevel(ListTemplate, ContinuePreviousList, ApplyTo, DefaultListBehavior, ApplyLevel);virtual; + Function ApplyNumberDefault(DefaultListBehavior);virtual; + Function ApplyOutlineNumberDefault(DefaultListBehavior);virtual; + Function CanContinuePreviousList(ListTemplate);virtual; + Function ConvertNumbersToText();virtual; + Function ListIndent();virtual; + Function ListOutdent();virtual; + Function RemoveNumbers(NumberType);virtual; + + // Properties + property List read ReadList; + property ListLevelNumber read ReadListLevelNumber write WriteListLevelNumber; + property ListPictureBullet read ReadListPictureBullet; + property ListString read ReadListString; + property ListTemplate read ReadListTemplate; + property ListType read ReadListType; + property ListValue read ReadListValue; + property SingleList read ReadSingleList; + property SingleListTemplate read ReadSingleListTemplate; + Function ReadSingleListTemplate();virtual; + Function ReadSingleList();virtual; + Function ReadListValue();virtual; + Function ReadListType();virtual; + Function ReadListTemplate();virtual; + Function ReadListString();virtual; + Function ReadListPictureBullet();virtual; + Function WriteListLevelNumber(value);virtual; + Function ReadListLevelNumber();virtual; + Function ReadList();virtual; + +End; + + +// ============== 实现 ================= // +Function TSDocxListFormat.Init(docx, pr); +Begin + docx_ := docx; + pr_ := pr; + document_ := self.Parent; + while not (document_ is class(TSDocxDocument)) do + document_ := document_.Parent; +End; + +Function TSDocxListFormat.GetNumId(type); +Begin + numid := document_.GetParam(type); + if not ifnil(numid) then return numid; + case type of + "BulletDefault": numid := docx_.NumberingObject().NumberId("bullet", 0); + "NumberDefault": numid := docx_.NumberingObject().NumberId("singlelevel", "decimal"); + "OutlineNumberDefault": numid := docx_.NumberingObject().NumberId("multilevel", "decimal"); + end; + document_.SetParam(type, numid); + return numid; +End; + +Function TSDocxListFormat.Apply();virtual; +Begin + pr_.Update("first"); +End; + +Function TSDocxListFormat.ApplyBulletDefault(DefaultListBehavior); +Begin + pr_.NumPr.Level := 0; + pr_.NumPr.NumId := self.GetNumId("BulletDefault"); + pr_.Update("first"); +End; + +Function TSDocxListFormat.ApplyNumberDefault(DefaultListBehavior); +Begin + pr_.NumPr.Level := 0; + pr_.NumPr.NumId := self.GetNumId("NumberDefault"); + pr_.Update("first"); +End; + +Function TSDocxListFormat.ApplyOutlineNumberDefault(DefaultListBehavior);virtual; +Begin + get_level := function(obj); + begin + if not ifObj(obj) then return ''; + level := obj.HeadingLevel(); + if level = "" then + begin + id := obj.Value("BasedOn", true); + return ##get_level(docx_.StyleObject().GetStyleById(id)); + end + end + value := pr_.Value("OutlineLevel"); + if ifnil(value) then + begin + obj := docx_.StyleObject().GetStyleById(styleid); + value := ##get_level(obj); + end + pr_.NumPr.Level := value; + pr_.NumPr.NumId := self.GetNumId("OutlineNumberDefault"); + pr_.Update("first"); +End; diff --git a/docx/listformat/TSDocxListFormatRange.tsf b/docx/listformat/TSDocxListFormatRange.tsf new file mode 100644 index 0000000..3e60a4a --- /dev/null +++ b/docx/listformat/TSDocxListFormatRange.tsf @@ -0,0 +1,177 @@ +Type TSDocxListFormatRange = Class(TSDocxListFormat) +Uses TSDocxEnumerations; + +public + Function Init(docx, rangeObj); + Function Apply();override; + +private + Function CallFunction(pf, value);overload; + Function CallFunction(pf);overload; + +private + paragraph_arr_; + +public + // Methods + Function ApplyBulletDefault(DefaultListBehavior);override; + Function ApplyListTemplate(ListTemplate, ContinuePreviousList, ApplyTo, DefaultListBehavior);override; + Function ApplyListTemplateWithLevel(ListTemplate, ContinuePreviousList, ApplyTo, DefaultListBehavior, ApplyLevel);override; + Function ApplyNumberDefault(DefaultListBehavior);override; + Function ApplyOutlineNumberDefault(DefaultListBehavior);override; + Function CanContinuePreviousList(ListTemplate);override; + Function ConvertNumbersToText();override; + Function ListIndent();override; + Function ListOutdent();override; + Function RemoveNumbers(NumberType);override; + + // Properties + Function ReadSingleListTemplate();override; + Function ReadSingleList();override; + Function ReadListValue();override; + Function ReadListType();override; + Function ReadListTemplate();override; + Function ReadListString();override; + Function ReadListPictureBullet();override; + Function WriteListLevelNumber(value);override; + Function ReadListLevelNumber();override; + Function ReadList();override; + +End; + + +// ============== 实现 ================= // +Function TSDocxListFormatRange.Init(docx, rangeObj); +Begin + class(TSDocxListFormat).Init(docx, nil); + paragraph_arr_ := sselect distinct(["tparagraph"]) from rangeObj.data_ end; +End; + +Function TSDocxListFormatRange.Apply();override; +Begin + CallFunction(ThisFunction(class(TSDocxListFormat).Apply), nil); +End; + +Function TSDocxListFormatRange.CallFunction(pf, value);overload; +Begin + for i:=0 to length(paragraph_arr_)-1 do + begin + pr_ := paragraph_arr_[i].pPr; + if not ifObj(pr_.Root()) then continue; + ##pf(value); + end +End; + +Function TSDocxListFormatRange.CallFunction(pf);overload; +Begin + ret := nil; + for i:=0 to length(paragraph_arr_)-1 do + begin + pr_ := paragraph_arr_[i].pPr; + if not ifObj(pr_.Root()) then continue; + cur := ##pf(); + if ifnil(ret) then ret := cur; + if ret <> cur then return TSDocxEnumerations.wdUndefined(); + end + return ret; +End; + +// Methods +Function TSDocxListFormatRange.ApplyBulletDefault(DefaultListBehavior);override; +Begin + CallFunction(ThisFunction(class(TSDocxListFormat).ApplyBulletDefault), DefaultListBehavior); +End; + +Function TSDocxListFormatRange.ApplyListTemplate(ListTemplate, ContinuePreviousList, ApplyTo, DefaultListBehavior);override; +Begin +End; + +Function TSDocxListFormatRange.ApplyListTemplateWithLevel(ListTemplate, ContinuePreviousList, ApplyTo, DefaultListBehavior, ApplyLevel);override; +Begin +End; + +Function TSDocxListFormatRange.ApplyNumberDefault(DefaultListBehavior);override; +Begin + CallFunction(ThisFunction(class(TSDocxListFormat).ApplyNumberDefault), DefaultListBehavior); +End; + +Function TSDocxListFormatRange.ApplyOutlineNumberDefault(DefaultListBehavior);override; +Begin + CallFunction(ThisFunction(class(TSDocxListFormat).ApplyOutlineNumberDefault), DefaultListBehavior); +End; + +Function TSDocxListFormatRange.CanContinuePreviousList(ListTemplate);override; +Begin + CallFunction(ThisFunction(class(TSDocxListFormat).CanContinuePreviousList), ListTemplate); +End; + +Function TSDocxListFormatRange.ConvertNumbersToText();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ConvertNumbersToText)); +End; + +Function TSDocxListFormatRange.ListIndent();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ListIndent)); +End; + +Function TSDocxListFormatRange.ListOutdent();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ListOutdent)); +End; + +Function TSDocxListFormatRange.RemoveNumbers(NumberType);override; +Begin + CallFunction(ThisFunction(class(TSDocxListFormat).RemoveNumbers), NumberType); +End; + +Function TSDocxListFormatRange.ReadSingleListTemplate();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ReadSingleListTemplate)); +End; + +Function TSDocxListFormatRange.ReadSingleList();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ReadSingleList)); +End; + +Function TSDocxListFormatRange.ReadListValue();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ReadListValue)); +End; + +Function TSDocxListFormatRange.ReadListType();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ReadListType)); +End; + +Function TSDocxListFormatRange.ReadListTemplate();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ReadListTemplate)); +End; + +Function TSDocxListFormatRange.ReadListString();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ReadListString)); +End; + +Function TSDocxListFormatRange.ReadListPictureBullet();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ReadListPictureBullet)); +End; + +Function TSDocxListFormatRange.WriteListLevelNumber(value);override; +Begin + CallFunction(ThisFunction(class(TSDocxListFormatRange).WriteListLevelNumber), Value); +End; + +Function TSDocxListFormatRange.ReadListLevelNumber();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ReadListLevelNumber)); +End; + +Function TSDocxListFormatRange.ReadList();override; +Begin + return CallFunction(ThisFunction(class(TSDocxListFormatRange).ReadList)); +End; + diff --git a/docx/prargraphformat/TSDocxParagraphFormat.tsf b/docx/paragraphformat/TSDocxParagraphFormat.tsf similarity index 98% rename from docx/prargraphformat/TSDocxParagraphFormat.tsf rename to docx/paragraphformat/TSDocxParagraphFormat.tsf index 46d59af..d975152 100644 --- a/docx/prargraphformat/TSDocxParagraphFormat.tsf +++ b/docx/paragraphformat/TSDocxParagraphFormat.tsf @@ -24,7 +24,7 @@ public Function TabHangingIndent(Count);virtual; Function TabIndent(Count);virtual; - // property + // Properties property AddSpaceBetweenFarEastAndAlpha read ReadAddSpaceBetweenFarEastAndAlpha write WriteAddSpaceBetweenFarEastAndAlpha; property AddSpaceBetweenFarEastAndDigit read ReadAddSpaceBetweenFarEastAndDigit write WriteAddSpaceBetweenFarEastAndDigit; property Alignment read ReadAlignment write WriteAlignment; @@ -161,8 +161,11 @@ End; Function TSDocxParagraphFormat.ReWrite(pr);virtual; Begin self.Reset(); - marshal := pr.Marshal()[0]; - pr_.Root().InsertAfterChild(marshal["children"]); + rpr := pr.Root().FirstChildElement("w:pPr"); + if not ifObj(rpr) then return; + marshal := rPr.Marshal()[0]; + node := class(TSXml).GetNode(pr_.Root(), "w:pPr", "first"); + class(TSXml).UpdateNode(node, marshal["attributes"], marshal["children"]); End; // Methods @@ -257,7 +260,7 @@ Begin return TSDocxEnumerations.wdTightFirstLineOnly(); "LastLineOnly": return TSDocxEnumerations.wdTightLastLineOnly(); - "none": + "none", nil: return TSDocxEnumerations.wdTightNone(); end; End; @@ -265,6 +268,7 @@ End; Function TSDocxParagraphFormat.WriteStyle(value);virtual; Begin obj := docx_.StyleObject().GetStyle(value); + if not obj then obj := docx_.StyleObject().AddDefaultStyle(value); pr_.StyleId := obj.StyleId; End; Function TSDocxParagraphFormat.ReadStyle();virtual; diff --git a/docx/prargraphformat/TSDocxParagraphFormatRange.tsf b/docx/paragraphformat/TSDocxParagraphFormatRange.tsf similarity index 99% rename from docx/prargraphformat/TSDocxParagraphFormatRange.tsf rename to docx/paragraphformat/TSDocxParagraphFormatRange.tsf index 63ee31d..b6e0cc4 100644 --- a/docx/prargraphformat/TSDocxParagraphFormatRange.tsf +++ b/docx/paragraphformat/TSDocxParagraphFormatRange.tsf @@ -113,7 +113,7 @@ End; Function TSDocxParagraphFormatRange.Init(docx, rangeObj); Begin class(TSDocxParagraphFormat).Init(docx, nil); - paragraph_arr_ := sselect distinct(["tparagraph"]) from rangeObj.Data end; + paragraph_arr_ := sselect distinct(["tparagraph"]) from rangeObj.data_ end; End; Function TSDocxParagraphFormatRange.Apply();override; diff --git a/docx/shading/TSDocxShading.tsf b/docx/shading/TSDocxShading.tsf index 4124039..6b5c36a 100644 --- a/docx/shading/TSDocxShading.tsf +++ b/docx/shading/TSDocxShading.tsf @@ -11,6 +11,7 @@ private color_; public + // Properties property BackgroundPatternColor read ReadBackgroundPatternColor write WriteBackgroundPatternColor; property BackgroundPatternColorIndex read ReadBackgroundPatternColorIndex write WriteBackgroundPatternColorIndex; property ForegroundPatternColor read ReadForegroundPatternColor write WriteForegroundPatternColor; diff --git a/docx/shading/TSDocxShadingRange.tsf b/docx/shading/TSDocxShadingRange.tsf index 4a1f1f1..8f3a024 100644 --- a/docx/shading/TSDocxShadingRange.tsf +++ b/docx/shading/TSDocxShadingRange.tsf @@ -3,6 +3,7 @@ Uses TSDocxEnumerations; public Function Init(rangeObj); + Function Apply();override; private Function GetShadingObjectByNode(node); @@ -36,6 +37,11 @@ Begin class(TSDocxShading).Init(nil); End; +Function TSDocxShadingRange.Apply();override; +Begin + CallFunction(ThisFunction(class(TSDocxShading).Apply), nil); +End; + Function TSDocxShadingRange.SplitRun(); Begin range_obj_.SplitRangeRun(); @@ -44,14 +50,14 @@ End; Function TSDocxShadingRange.GetShading(arr, hash); Begin - if arr["entirety"] then + if arr.Entirety then begin - if not ifnil(hash[arr["entirety"]]) then nil; - hash[arr["entirety"]] := true; - shading := GetShadingObjectByNode(arr["entirety"]); + if not ifnil(hash[arr.Entirety]) then nil; + hash[arr.Entirety] := true; + shading := GetShadingObjectByNode(arr.Entirety); end else begin - trun := arr["trun"]; + trun := arr.TRun; if not ifObj(trun.Root()) then return nil; shading := new TSDocxShading(self.Application, self.Creator, self.Parent); shading.Init(trun.rPr.Shading); @@ -91,10 +97,9 @@ Begin // 这样设计是为了段落走走段落的shading,table走table的,cell走cell的 SplitRun(); hash := array(); - range_arr := rangeObj.GetInfo(); - for i:=0 to length(range_arr)-1 do + for i:=0 to range_obj_.Size()-1 do begin - shading := GetShading(range_arr[i], hash); + shading := GetShading(range_obj_[i], hash); if ifnil(shading) then continue; pf := FindFunction(fname, shading); pf.Do(value); @@ -105,10 +110,9 @@ Function TSDocxShadingRange.CallFunction(fname);overload; Begin hash := array(); ret := nil; - range_arr := rangeObj.GetInfo(); - for i:=0 to length(range_arr)-1 do + for i:=0 to range_obj_.Size()-1 do begin - shading := GetShading(range_arr[i], hash); + shading := GetShading(range_obj_[i], hash); if ifnil(shading) then continue; pf := FindFunction(fname, shading); r := pf.Do(); diff --git a/docx/utils/TSWdCommon.tsf b/docx/utils/TSWdCommon.tsf deleted file mode 100644 index b1a03a1..0000000 --- a/docx/utils/TSWdCommon.tsf +++ /dev/null @@ -1,229 +0,0 @@ -Type TSWdCommon = Class - - Class Function AddRun(rootNode, parentNode, runNode, tParagraph, pStart, pEnd, pTotal, arr); - Begin - run_obj := TOfficeObj("TRun"); - run_obj.Init(runNode); - text := ifObj(runNode) ? run_obj.Text() : ""; - len := text ? length(text) : 1; - - if pTotal + len > pStart then - begin - length := length(arr); - arr[length]["tparagraph"] := tparagraph; - arr[length]["trun"] := run_obj; - arr[length]["text"] := text; - arr[length]["root"] := rootNode; - arr[length]["parent"] := parentNode; - // 左边切割 - if pTotal < pstart and pTotal + len > pStart + 1 then - arr[length]["lsplit"] := pStart - pTotal; // 左边丢弃的字符数 - // 右边切割 - if pTotal + len > pEnd then - arr[length]["rsplit"] := pTotal + len - pEnd; // 右边丢弃的字符数 - end - return len; - End; - - Class Function SplitRange(root, startNode, pStart, pEnd, pTotal, arr); - Begin - node := startNode.FirstChildElement(); - while ifObj(node) do - begin - case node.GetName() of - "w:p": - begin - paragraph_obj := TOfficeObj("TParagraph"); - paragraph_obj.Init(node); - if paragraph_obj.Empty() then - begin - AddRun(root, startNode, nil, paragraph_obj, pStart, pEnd, pTotal, arr); - end - else begin - paragraph_len := length(arr); // 标记段落完整的起始位置 - sub_node := node.FirstChildElement(); - while ifObj(sub_node) do - begin - case sub_node.GetName() of - "w:r": - begin - pTotal += AddRun(root, startNode, sub_node, paragraph_obj, pStart, pEnd, pTotal, arr); - if pTotal >= pEnd then return 1; - end - - "w:ins", "w:del": - begin - run_node := sub_node.FirstChildElement("w:r"); - while ifObj(run_node) do - begin - AddRun(paragraph_obj, root, run_node, pStart, pEnd, pTotal, arr); - run_node := run_node.NextElement("w:r"); - end - end - end; - sub_node := sub_node.NextElement(); - end - for i:=paragraph_len to length(arr)-1 do - arr[i]["entirety"] := node; - end - pTotal += 1; - if pTotal >= pEnd then return 1; - end - - "w:tbl": - begin - table_len := length(arr); - tr := node.FirstChildElement("w:tr"); - while ifObj(tr) do - begin - tc := tr.FirstChildElement("w:tc"); - while ifObj(tc) do - begin - cell_len := length(arr); - flag := SplitRange(root, tc, pStart, pEnd, pTotal, arr); - if flag then return 1; - tc := tc.NextElement("w:tc"); - if pTotal >= pEnd then return 1; - for i:=cell_len to length(arr)-1 do - arr[i]["entirety"] := node; - end - tr := tr.NextElement("w:tr"); - pTotal += 1; - if pTotal >= pEnd then return 1; - end - for i:=table_len to length(arr)-1 do - arr[i]["entirety"] := node; - end - end; - node := node.NextElement(); - end - End; - - Class Function AddRange(root, startNode, findNode, tParagraph, runNode, arr); - Begin - run_obj := TOfficeObj("TRun"); - run_obj.Init(runNode); - length := length(arr); - arr[length]["tparagraph"] := tParagraph; - arr[length]["trun"] := run_obj; - arr[length]["root"] := root; - arr[length]["parent"] := startNode; - arr[length]["entirety"] := findNode; - text := ifObj(runNode) ? run_obj.Text() : ""; - return text ? length(text) : 1; - End; - - Class Function ParagraphRange(root, startNode, findNode, node, pend, arr); - Begin - paragraph_obj := TOfficeObj("TParagraph"); - paragraph_obj.Init(node); - if paragraph_obj.Empty() then - begin - AddRange(root, startNode, findNode, paragraph_obj, nil, arr); - end - else begin - sub_node := node.FirstChildElement(); - while ifObj(sub_node) do - begin - case sub_node.GetName() of - "w:r": pend += AddRange(root, startNode, findNode, paragraph_obj, sub_node, arr); - - "w:ins", "w:del": - begin - run_node := sub_node.FirstChildElement("w:r"); - while ifObj(run_node) do - begin - pend += AddRange(root, findNode, paragraph_obj, run_node, arr); - run_node := run_node.NextElement("w:r"); - end - end - end; - sub_node := sub_node.NextElement(); - end - end - pend += 1; - End; - - Class Function CalculateRange(root, startNode, findNode, findFlag, pbegin, pend, arr); - Begin - if findFlag then arr := array(); - node := startNode.FirstChildElement(); - while ifObj(node) do - begin - if node.Eq(findNode) then - begin - find_flag2 := true; - arr := array(); - end - case node.GetName() of - "w:p": ParagraphRange(root, startNode, findNode, node, pend, arr); - "w:tbl": - begin - tr := node.FirstChildElement("w:tr"); - while ifObj(tr) do - begin - tc := tr.FirstChildElement("w:tc"); - while ifObj(tc) do - begin - tc_node := tc; - new_flag := tc_node.Eq(findNode); - if new_flag then temp := pbegin; // 把pbegin存起来,防止递归覆盖 - flag := CalculateRange(root, tc_node, findNode, new_flag, pbegin, pend, arr); - if new_flag then pbegin := temp; - if flag then return 1; - tc := tc.NextElement("w:tc"); - end - tr := tr.NextElement("w:tr"); - pend += 1; - end - end - end; - if find_flag2 then return 1; - if not flag then pbegin := pend; - node := node.NextElement(); - end - if findFlag then return 1; - End; - - Class Function SplitRangeRun(rangeArr);overload; - Begin - for i:=0 to length(rangeArr)-1 do - rangeArr[i] := SplitSingleRangeRun(rangeArr[i]); - End; - - Class Function SplitSingleRangeRun(arr);overload; - Begin - insert_run := function(root, node); - begin - new_node := root.InsertAfterChild(node, "element", "w:r"); - run := TOfficeObj("TRun"); - run.Init(new_node); - return run; - end - paragraph := arr["tparagraph"]; - run := arr["trun"]; - text := arr["text"]; - if arr["lsplit"] then // 分割左边 - begin - lpos := arr["lsplit"]; - run.SetText(text[:lpos]); - run := ##insert_run(paragraph.Root(), run.Root()); - text := text[lpos + 1:]; - run.SetText(text); - arr["text"] := text; - arr["lsplit"] := nil; - end - if arr["rsplit"] then // 分割右边的run - begin - rpos := length(text) - arr["rsplit"]; - run.SetText(text[1:rpos]); - new_run := ##insert_run(paragraph.Root(), run.Root()); - new_run.SetText(text[rpos+1:]); - arr["rsplit"] := nil; - arr["text"] := text[1:rpos]; - end - arr["trun"] := run; - return arr; - End; - -End; diff --git a/docx/utils/TSWdRange.tsf b/docx/utils/TSWdRange.tsf index 4f8ebfc..8b9995f 100644 --- a/docx/utils/TSWdRange.tsf +++ b/docx/utils/TSWdRange.tsf @@ -1,36 +1,43 @@ Type TSWdRange = Class - public Function Create(rootNode, startP, endP);overload; Function Create(rootNode, targetNode);overload; Function Init(); + Function Operator[](index); + Function Run(); + Function Refresh(); Function GetStart(); Function GetEnd(); Function SplitRun();overload; - Function SplitRun(arr);overload; - Function Clear(); - Function Print(); + Function SplitRun(index);overload; + Function Clear(deleteAll); + Function Size(); + Function Root(); -public - Data; // 管理range结构的数组,字段如下 - // lsplit: 左边丢弃的字符数 - // rsplit: 右边丢弃的字符数 - // tparagraph: TOfficeObj("TParagraph")对象 - // trun: TOfficeObj("TRun")对象 - // text: 文本内容 - // root: 根节点 - // parent: 父节点 - // entirety: 是否是完整的段落/表格/单元格 + Function Print(); + Begin + println("data = {}", data_); + End; private Function FindRangeByPosition(startNode); Function FindRangeByNode(startNode); Function AddEntirety(len, node); - Function AddRunInfo(parentNode, runNode, tParagraph); - Function AddRunInfo2(parentNode, runNode, tParagraph); + Function AddRunInfo(runNode, tParagraph); + Function AddRunInfo2(runNode, tParagraph); Function ParagraphRange(node); +public + data_; // 管理range结构的数组,字段如下 + // lsplit: 左边丢弃的字符数 + // rsplit: 右边丢弃的字符数 + // tparagraph: TOfficeObj("TParagraph")对象 + // trun: TOfficeObj("TRun")对象 + // text: 文本内容 + // entirety: 是否是完整的段落/表格/单元格 + // -- 以便在对range操作时候知道操作一个段落还是一个run,比如range.shading range.Border + private start_position_; // 开始位置 end_position_; // 结束位置, 开始与结束遵循左闭右开原则 @@ -39,15 +46,69 @@ private target_node_; // 目标节点,使用paragraph.Range,table.Range, cell.Range时用 split_flag_; // 切割标志 + proxy_; // 代理类,提供外部对数组data_的读写 + End; +Type Proxy = Class +public + Function Create(obj); + + property TRun read ReadTRun write WriteTRun; + property TParagraph read ReadTParagraph write WriteTParagraph; + property Entirety read ReadEntirety write WriteEntirety; + Function WriteEntirety(value); + Function ReadEntirety(); + Function WriteTParagraph(value); + Function ReadTParagraph(); + Function WriteTRun(value); + Function ReadTRun(); + + [weakref]obj_; + index_; +End; + +Function Proxy.Create(obj); +Begin + obj_ := obj; + index_ := nil; +End; + +Function Proxy.WriteEntirety(value); +Begin + obj_.data_[index_]["entirety"] := value; +End; +Function Proxy.ReadEntirety(); +Begin + return obj_.data_[index_]["entirety"]; +End; + +Function Proxy.WriteTParagraph(value); +Begin + obj_.data_[index_]["tparagraph"] := value; +End; +Function Proxy.ReadTParagraph(); +Begin + return obj_.data_[index_]["tparagraph"]; +End; + +Function Proxy.WriteTRun(value); +Begin + obj_.data_[index_]["trun"] := value; +End; +Function Proxy.ReadTRun(); +Begin + return obj_.data_[index_]["trun"]; +End; + +// TSWdRange实现 Function TSWdRange.Create(rootNode, startP, endP);overload; Begin root_node_ := rootNode; start_position_ := startP; end_position_ := endP; - targetNode := nil; - Init(); + target_node_ := nil; + self.Init(); End; Function TSWdRange.Create(rootNode, targetNode);overload; @@ -56,28 +117,46 @@ Begin target_node_ := targetNode; start_position_ := nil; end_position_ := nil; - Init(); + self.Init(); End; Function TSWdRange.Init(); Begin cur_position_ := 0; split_flag_ := false; - Data := array(); - Run(); + data_ := array(); + self.Run(); + proxy_ := new Proxy(self); +End; + +Function Operator TSWdRange.[](index); +Begin + proxy_.index_ := index; + return proxy_; End; Function TSWdRange.Run(); Begin if target_node_ then - FindRangeByNode(target_node_); + self.FindRangeByNode(target_node_); else - FindRangeByPosition(root_node_); + self.FindRangeByPosition(root_node_); End; -Function TSWdRange.Print(); +Function TSWdRange.Refresh(); Begin - println("print... {}", Data); + if target_node_ then self.FindRangeByNode(target_node_); +End; + +Function TSWdRange.Size(); +Begin + return length(data_); +End; + +Function TSWdRange.Root(); +Begin + node := root_node_; + return node; End; Function TSWdRange.GetStart(); @@ -95,44 +174,65 @@ End; Function TSWdRange.SplitRun();overload; Begin if split_flag_ then return; - for i:=0 to length(Data)-1 do - Data[i] := SplitRun(Data[i]); + for i:=0 to length(data_)-1 do + self.SplitRun(i); split_flag_ := true; End; -Function TSWdRange.SplitRun(arr);overload; +Function TSWdRange.SplitRun(index);overload; Begin - insert_run := function(root, node); + if ifnil(data_[index]["lsplit"]) and ifnil(data_[index]["rsplit"]) then return data_[index]; + paragraph := data_[index]["tparagraph"]; + run := data_[index]["trun"]; + text := data_[index]["text"]; + if data_[index]["lsplit"] then // 分割左边 begin - new_node := root.InsertAfterChild(node, "element", "w:r"); - run := TOfficeObj("TRun"); - run.Init(new_node); - return run; + lpos := data_[index]["lsplit"]; + run.SetText(AnsiToUtf8(leftstr(text, lpos))); + new_run := paragraph.AppendRun(run); + new_run.CopyFontFormat(run); + text := rightstr(text, lengthw(text)-lpos); + new_run.SetText(AnsiToUtf8(text)); + data_[index]["text"] := text; + data_[index]["lsplit"] := nil; + run := new_run; end - if ifnil(arr["lsplit"]) and ifnil(arr["rsplit"]) then return arr; - paragraph := arr["tparagraph"]; - run := arr["trun"]; - text := arr["text"]; - if arr["lsplit"] then // 分割左边 + if data_[index]["rsplit"] then // 分割右边的run begin - lpos := arr["lsplit"]; - run.SetText(text[:lpos]); - run := ##insert_run(paragraph.Root(), run.Root()); - text := text[lpos + 1:]; - run.SetText(text); - arr["text"] := text; - arr["lsplit"] := nil; + rpos := data_[index]["rsplit"]; + new_run := paragraph.AppendRun(run); + new_run.CopyFontFormat(run); + new_run.SetText(AnsiToUtf8(rightstr(text, rpos))); + new_text := AnsiToUtf8(leftstr(text, lengthw(text) - rpos)); + run.SetText(new_text); + data_[index]["rsplit"] := nil; + data_[index]["text"] := new_text; end - if arr["rsplit"] then // 分割右边的run + data_[index]["trun"] := run; +End; + +Function TSWdRange.Clear(deleteAll); +Begin + self.SplitRun(); + arr := array(); + first := data_[0]; + para := first["tparagraph"]; + if deleteAll then arr[length(arr)] := para.Root(); + for i:=1 to length(data_)-1 do begin - rpos := length(text) - arr["rsplit"]; - run.SetText(text[1:rpos]); - new_run := ##insert_run(paragraph.Root(), run.Root()); - new_run.SetText(text[rpos+1:]); - arr["rsplit"] := nil; - arr["text"] := text[1:rpos]; + if data_[i]["tparagraph"] <> para then + begin + arr[length(arr)] := data_[i]["tparagraph"].Root(); + end + else begin + p := data_[i]["tparagraph"]; + r := data_[i]["trun"]; + if ifObj(r.Root()) then p.Root().DeleteChild(r.Root()); + end end - arr["trun"] := run; + first["trun"].ClearText(); + data_ := array(); + if not deleteAll then data_[0] := first; return arr; End; @@ -141,7 +241,7 @@ Begin node := startNode.FirstChildElement(); while ifObj(node) do begin - len := length(Data); // 标记完整段落/表格的起始位置 + len := length(data_); // 标记完整段落/表格的起始位置 case node.GetName() of "w:p": begin @@ -149,7 +249,7 @@ Begin paragraph_obj.Init(node); if paragraph_obj.Empty() then // 空段落 begin - AddRunInfo(startNode, nil, paragraph_obj); + self.AddRunInfo(nil, paragraph_obj); end else begin sub_node := node.FirstChildElement(); @@ -158,7 +258,7 @@ Begin case sub_node.GetName() of "w:r": begin - AddRunInfo(startNode, sub_node, paragraph_obj); + self.AddRunInfo(sub_node, paragraph_obj); if cur_position_ >= end_position_ then return 1; end @@ -167,7 +267,7 @@ Begin run_node := sub_node.FirstChildElement("w:r"); while ifObj(run_node) do begin - AddRunInfo(startNode, run_node, paragraph_obj); + self.AddRunInfo(run_node, paragraph_obj); if cur_position_ >= end_position_ then return 1; run_node := run_node.NextElement("w:r"); end @@ -188,11 +288,11 @@ Begin tc := tr.FirstChildElement("w:tc"); while ifObj(tc) do begin - cell_len := length(Data); - flag := FindRangeByPosition(tc); + cell_len := length(data_); + flag := self.FindRangeByPosition(tc); if flag then return 1; if cur_position_ >= end_position_ then return 1; - AddEntirety(cell_len, tc); + self.AddEntirety(cell_len, tc); tc := tc.NextElement("w:tc"); end cur_position_ += 1; @@ -201,7 +301,7 @@ Begin end end end; - AddEntirety(len, node); + self.AddEntirety(len, node); if cur_position_ >= end_position_ then return 1; node := node.NextElement(); end @@ -209,32 +309,31 @@ End; Function TSWdRange.AddEntirety(len, node); Begin - for i:=len to length(Data)-1 do - Data[i]["entirety"] := node; + for i:=len to length(data_)-1 do + data_[i]["entirety"] := node; End; -Function TSWdRange.AddRunInfo(parentNode, runNode, tParagraph); +Function TSWdRange.AddRunInfo(runNode, tParagraph); Begin run_obj := TOfficeObj("TRun"); run_obj.Init(runNode); text := ifObj(runNode) ? run_obj.Text() : ""; - len := text ? length(text) : 1; + if class(TSXml).IsUtf8() then text := Utf8ToAnsi(text); + len := text ? lengthw(text) : 1; if cur_position_ + len > start_position_ then begin - length := length(Data); - Data[length]["tparagraph"] := tparagraph; - Data[length]["trun"] := run_obj; - Data[length]["text"] := text; - Data[length]["root"] := root_node_; - Data[length]["parent"] := parentNode; + length := length(data_); + data_[length]["tparagraph"] := tparagraph; + data_[length]["trun"] := run_obj; + data_[length]["text"] := text; // 左边切割,左边丢弃的字符数 - if cur_position_ < start_position_ and cur_position_ + len > start_position_ + 1 then - Data[length]["lsplit"] := start_position_ - cur_position_; + if cur_position_ < start_position_ and cur_position_ + len >= start_position_ + 1 then + data_[length]["lsplit"] := start_position_ - cur_position_; // 右边切割,右边丢弃的字符数 if cur_position_ + len > end_position_ then - Data[length]["rsplit"] := cur_position_ + len - end_position_; + data_[length]["rsplit"] := cur_position_ + len - end_position_; end cur_position_ += len; End; @@ -246,12 +345,12 @@ Begin node := tc.FirstChildElement(); while ifObj(node) do begin - FindRangeByNode(node); + self.FindRangeByNode(node); node := node.NextElement(); end end case startNode.GetName() of - "w:p": ParagraphRange(startNode); + "w:p": self.ParagraphRange(startNode); "w:tbl": begin tr := startNode.FirstChildElement("w:tr"); @@ -279,21 +378,21 @@ Begin paragraph_obj.Init(node); if paragraph_obj.Empty() then begin - AddRunInfo2(nil, nil, paragraph_obj); + self.AddRunInfo2(nil, paragraph_obj); end else begin sub_node := node.FirstChildElement(); while ifObj(sub_node) do begin case sub_node.GetName() of - "w:r": AddRunInfo2(nil, sub_node, paragraph_obj); + "w:r": self.AddRunInfo2(sub_node, paragraph_obj); "w:ins", "w:del": begin run_node := sub_node.FirstChildElement("w:r"); while ifObj(run_node) do begin - AddRunInfo2(nil, run_obj, paragraph_obj); + self.AddRunInfo2(run_node, paragraph_obj); run_node := run_node.NextElement("w:r"); end end @@ -303,38 +402,14 @@ Begin end End; -Function TSWdRange.AddRunInfo2(parentNode, runNode, tParagraph); +Function TSWdRange.AddRunInfo2(runNode, tParagraph); Begin run_obj := TOfficeObj("TRun"); run_obj.Init(runNode); - length := length(Data); - Data[length]["tparagraph"] := tParagraph; - Data[length]["trun"] := run_obj; - Data[length]["root"] := root_node_; - Data[length]["parent"] := parentNode; - Data[length]["entirety"] := target_node_; + length := length(data_); + data_[length]["tparagraph"] := tParagraph; + data_[length]["trun"] := run_obj; + data_[length]["entirety"] := target_node_; End; -Function TSWdRange.Clear(); -Begin - SplitRun(); - first := Data[0]; - para := first["tparagraph"]; - index := 0; - for i:=1 to length(Data)-1 do - begin - if Data[i]["tparagraph"] <> para then - begin - parent := Data[i]["parent"]; - parent.DeleteChild(Data[i]["tparagraph"].Root()); - end - else begin - p := Data[i]["tparagraph"]; - r := Data[i]["trun"]; - if ifObj(p.Root()) and ifObj(r.Root()) then p.Root().DeleteChild(r.Root()); - end - end - Data := array(); - Data[0] := first; -End; diff --git a/test/docx_vba_help.tsl b/test/docx_vba_help.tsl index 35bfcb7..c830ec3 100644 --- a/test/docx_vba_help.tsl +++ b/test/docx_vba_help.tsl @@ -1,5 +1,4 @@ Uses TSDocxEnumerations; - Application := new TSDocxApplication(); openpath := "D://temp//default.docx"; @@ -10,15 +9,455 @@ document.Activate; println("Documents.Count = {}", Application.Documents.Count); ActiveDocument := Application.ActiveDocument; println("ActiveDocument.Name = {}", ActiveDocument.Name); -println("\n"); -ActiveDocument.Paragraphs.Add; -para := ActiveDocument.Paragraphs.Last; -para.Range.Text := "TSVBA帮助文档"; -println("para = {}", para); -// para.Range.Font.Size := 20; -para.Format.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); -para.Format.Apply(); // 写属性后要apply -// ActiveDocument.SaveAs2(FileName : savepath); -// println("ActiveDocument.SaveAs2 = {}", savepath); +FirstPage(ActiveDocument); +Preface(ActiveDocument); +SupportedList(ActiveDocument); +FAQ(ActiveDocument); +AddTablesOfContents(ActiveDocument); +ActiveDocument.SaveAs2(FileName : savepath); +println("ActiveDocument.SaveAs2 = {}", savepath); +return; + +Function FirstPage(ActiveDocument); +Begin + para := ActiveDocument.Paragraphs.Last; + para.Range.Text := "TSVBA"; + para.Range.InsertBefore("天软"); + para.Range.InsertAfter("帮助文档"); + para.Range.Font.Bold := true; + para.Range.Font.Size := 25; + para.Range.Font.Apply(); + para.Format.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + para.Format.Style := "Title"; + para.Format.Apply(); // 写属性后要apply + + ActiveDocument.Paragraphs.Add; + ActiveDocument.Paragraphs(2).Range.InsertParagraphAfter(); + ActiveDocument.Paragraphs(2).Range.InsertParagraphBefore(); + range := ActiveDocument.Paragraphs(3).Range; + range.Collapse(TSDocxEnumerations.wdCollapseEnd()); + table := ActiveDocument.Tables.Add(Range:=range, NumRows:=3, NumColumns:=2, DefaultTableBehavior:=TSDocxEnumerations.wdWord9TableBehavior); + println("ActiveDocument.Paragraphs.Count = {}", ActiveDocument.Paragraphs.Count); + table.Columns(1).Width := 120; + table.Columns(2).Width := 320; + data := array(("文档名称", "TSVBA"), ("文档版本", "Version 1.0"), ("修订日期", Datetimetostr(now()))); + for i:=1 to 3 do + begin + cell := table.Cell(i, 1); + cell.Shading.Texture := TSDocxEnumerations.wdTexture27Pt5Percent; + cell.Shading.ForegroundPatternColor := TSDocxEnumerations.wdColorAutomatic; + cell.Shading.BackgroundPatternColor := TSDocxEnumerations.wdColorGray15; + cell.Shading.Apply(); + cell.Range.Text := data[i-1][0]; + cell.Range.Font.Bold := true; + cell.Range.Font.Apply(); + + cell := table.Cell(i, 2); + cell.VerticalAlignment := TSDocxEnumerations.wdCellAlignVerticalCenter; + cell.Range.Text := data[i-1][1]; + cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + cell.Range.ParagraphFormat.Apply(); + end + ActiveDocument.Paragraphs.Add; + para := ActiveDocument.Paragraphs.Last; + para.Range.InsertBreak(TSDocxEnumerations.wdPageBreak()); +End; + +Function AddTitle(ActiveDocument, text, level); +Begin + ActiveDocument.Paragraphs.Add; + para := ActiveDocument.Paragraphs.Last; + info := array( + (22, TSDocxEnumerations.wdViolet(), TSDocxEnumerations.wdOutlineLevel1(), 0), + (16, TSDocxEnumerations.wdDarkRed(), TSDocxEnumerations.wdOutlineLevel2(), 2), + (16, TSDocxEnumerations.wdTeal(), TSDocxEnumerations.wdOutlineLevel3(), 15), + ); + index := level - 1; + para.Range.Text := text; + para.Range.Font.Size := info[index][0]; + para.Range.Font.Bold := true; + para.Range.Font.ColorIndex := info[index][1]; + para.Range.Font.Apply(); + para.Format.OutlineLevel := info[index][2]; + para.Format.LeftIndent := info[index][3]; + // para.Format.CharacterUnitLeftIndent := 0; + para.Format.Apply(); + para.Range.ListFormat.ApplyOutlineNumberDefault(); +End; + +Function Preface(ActiveDocument); +Begin + AddTitle(ActiveDocument, "前言", 1); + para := ActiveDocument.Paragraphs.Last; + para.Format.PageBreakBefore := true; + para.Format.Apply(); + + ActiveDocument.Paragraphs.Add; + para := ActiveDocument.Paragraphs.Last; + para.Range.Text := "该文档由docx_vba_help.tsl脚本自动生成。"; + para.Range.Font.Size := 14; + para.Range.Font.Italic := true; + para.Range.Font.ColorIndex := TSDocxEnumerations.wdPink(); + para.Range.Font.Apply(); + para.Format.CharacterUnitFirstLineIndent := 2; + para.Format.FirstLineIndent := 20; + para.Format.Apply(); + font := para.Range.Font.Duplicate; + format := para.Format.Duplicate; + + ActiveDocument.Paragraphs.Add; + para := ActiveDocument.Paragraphs.Last; + para.Range.Text := "本项目基于TSOffice,使用前请先部署TSOffice。该项目以类VBA的方式,用TSL实现对excel、word的操作。"; + para.Range.Font := font; + para.Format := format; + para.Range.Font.Italic := false; + para.Range.Font.ColorIndex := TSDocxEnumerations.wdBlack(); + para.Range.Font.Apply(); + font := para.Range.Font.Duplicate; + format := para.Format.Duplicate; + + ActiveDocument.Paragraphs.Add; + para := ActiveDocument.Paragraphs.Last; + para.Range.Text := "项目目前仅支持常用的操作,比如对段落、表格的操作。需注意该项目在使用时可能存在与VBA有差异的情况。具体支持列表如下:"; + para.Range.Font := font; + para.Format := format; +End; + +Function SupportedList(ActiveDocument); +Begin + ActiveDocument.Paragraphs.Add; + AddTitle(ActiveDocument, "TSVBA支持对象", 1); + + println("\n\nAuto generate classInfo.."); + path := "D:\\code\\tinysoft\\OfficeVBA\\docx\\"; + files := array( + path + "TSDocxApplication.tsf", + path + "border//TSDocxBorder.tsf", + path + "border//TSDocxBorders.tsf", + path + "TSDocxCell.tsf", + path + "TSDocxCells.tsf", + path + "TSDocxColumn.tsf", + path + "TSDocxColumns.tsf", + path + "TSDocxDocument.tsf", + path + "TSDocxDocuments.tsf", + path + "font//TSDocxFont.tsf", + path + "listformat//TSDocxListFormat.tsf", + path + "TSDocxTable.tsf", + path + "TSDocxTables.tsf", + path + "TSDocxTablesOfContents.tsf", + path + "paragraphformat//TSDocxParagraphFormat.tsf", + path + "TSDocxParagraphs.tsf", + path + "TSDocxParagraph.tsf", + path + "TSDocxRange.tsf", + path + "TSDocxRows.tsf", + path + "TSDocxRow.tsf", + path + "shading//TSDocxShading.tsf", + ); + // files := array( + // path + "TSDocxTables.tsf", + // ); + for i:=0 to length(files)-1 do + begin + file := files[i]; + name := ExtractFileName(file); + name := name[7:length(name)-4]; + AddTitle(ActiveDocument, name, 2); + + methods := array(); + properties := array(); + LoadClassInfo(file, methods, properties); + AddMethods(ActiveDocument, methods); + AddProperties(ActiveDocument, properties); + println("file = {}, is OK!", file); + end +End; + +Function AddMethods(ActiveDocument, arr); +Begin + if not istable(arr) then return; + methods := array(); + for k, v in arr do + if v = 2 then methods[k] := v; + for k, v in arr do + methods[k] := v; + + AddTitle(ActiveDocument, "方法支持情况", 3); + para := ActiveDocument.Paragraphs.Last; + row := length(methods) + 1; + para.Range.Collapse(TSDocxEnumerations.wdCollapseEnd()); + table := ActiveDocument.Tables.Add(Range := para.Range, NumRows := row, NumColumns := 2, DefaultTableBehavior := TSDocxEnumerations.wdWord9TableBehavior); + table.Columns(1).Width := 220; + table.Columns(2).Width := 220; + + init_title := function(cell, title); + begin + cell.Shading.Texture := TSDocxEnumerations.wdTexture12Pt5Percent; + cell.Shading.ForegroundPatternColor := TSDocxEnumerations.wdColorAutomatic; + cell.Shading.BackgroundPatternColorIndex := TSDocxEnumerations.wdTurquoise; + cell.Shading.Apply(); + cell.Range.Text := title; + cell.Range.Font.Bold := true; + cell.Range.Font.Size := 14; + cell.Range.Font.ColorIndex := TSDocxEnumerations.wdRed(); + cell.Range.Font.Apply(); + cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + cell.Range.ParagraphFormat.Apply(); + border := cell.Borders(TSDocxEnumerations.wdBorderBottom); + border.LineStyle := TSDocxEnumerations.wdLineStyleTriple(); + border.ColorIndex := TSDocxEnumerations.wdBlue(); + border.Apply(); + end + ##init_title(table.Cell(1, 1), "VBA函数"); + ##init_title(table.Cell(1, 2), "TSVBA是否支持"); + i := 2; + for k, v in methods do + begin + cell := table.Cell(i, 1); + cell.Range.Text := k; + cell.Range.Font.NameAscii := "Consolas"; + cell.Range.Font.NameFarEast := "微软雅黑"; + cell.Range.Font.Size := 11; + cell.Range.Font.Apply(); + cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + cell.Range.ParagraphFormat.Apply(); + cell := table.Cell(i, 2); + cell.Range.Text := v = 2 ? "✅" : "❌"; + cell.Range.Font.NameAscii := "Segoe UI Emoji"; + cell.Range.Font.NameOther := "Segoe UI Emoji"; + cell.Range.Font.NameBi := "Segoe UI Emoji"; + cell.Range.Font.Size := 11; + cell.Range.Font.Apply(); + cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + cell.Range.ParagraphFormat.Apply(); + i++; + end +End; + +Function AddProperties(ActiveDocument, arr); +Begin + if not istable(arr) then return; + properties := array(); + for k, v in arr do + if v["r"] = 2 or v["w"] = 2 then properties[k] := v; + for k, v in arr do + properties[k] := v; + + AddTitle(ActiveDocument, "属性支持情况", 3); + + row := length(properties) + 2; + para := ActiveDocument.Paragraphs.Last; + para.Range.Collapse(TSDocxEnumerations.wdCollapseEnd()); + table := ActiveDocument.Tables.Add(Range := para.Range, NumRows := row, NumColumns := 4, DefaultTableBehavior := TSDocxEnumerations.wdWord9TableBehavior); + table.Columns(1).Width := 110; + table.Columns(2).Width := 110; + table.Columns(3).Width := 110; + table.Columns(4).Width := 110; + table.Cell(1, 1).Merge(table.Cell(1, 2)); + table.Cell(1, 3).Merge(table.Cell(1, 4)); + + init_title := function(cell, title); + begin + cell.Shading.Texture := TSDocxEnumerations.wdTexture22Pt5Percent; + cell.Shading.ForegroundPatternColor := TSDocxEnumerations.wdColorAutomatic; + cell.Shading.BackgroundPatternColor := TSDocxEnumerations.wdColorLime; + cell.Shading.Apply(); + cell.Range.Text := title; + cell.Range.Font.Bold := true; + cell.Range.Font.Size := 14; + cell.Range.Font.ColorIndex := TSDocxEnumerations.wdRed(); + cell.Range.Font.Apply(); + cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + cell.Range.ParagraphFormat.Apply(); + border := cell.Borders(TSDocxEnumerations.wdBorderBottom); + border.LineStyle := TSDocxEnumerations.wdLineStyleTriple(); + border.ColorIndex := TSDocxEnumerations.wdBlue(); + border.Apply(); + end + ##init_title(table.Cell(1, 1), "VBA属性"); + ##init_title(table.Cell(1, 3), "TSVBA是否支持"); + init_info := function(cell, content); + begin + cell.Range.Text := content; + cell.Range.Font.NameAscii := "Consolas"; + cell.Range.Font.NameFarEast := "微软雅黑"; + cell.Range.Font.Size := 12; + cell.Range.Font.ColorIndex := TSDocxEnumerations.wdViolet(); + cell.Range.Font.Apply(); + cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + cell.Range.ParagraphFormat.Apply(); + cell.Shading.Texture := TSDocxEnumerations.wdTexture7Pt5Percent; + cell.Shading.ForegroundPatternColor := TSDocxEnumerations.wdColorAutomatic; + cell.Shading.BackgroundPatternColor := TSDocxEnumerations.wdColorGray30; + cell.Shading.Apply(); + end + ##init_info(table.Cell(2, 1), "属性名称"); + ##init_info(table.Cell(2, 2), "读写"); + ##init_info(table.Cell(2, 3), "读"); + ##init_info(table.Cell(2, 4), "写"); + + i := 3; + for k, v in properties do + begin + cell := table.Cell(i, 1); + // println("k = {}", k); + cell.Range.Text := k; + cell.Range.Font.NameAscii := "Consolas"; + cell.Range.Font.NameFarEast := "微软雅黑"; + cell.Range.Font.Size := 11; + cell.Range.Font.Apply(); + cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + cell.Range.ParagraphFormat.Apply(); + + content := ""; + if v["r"] then content += "读"; + if v["w"] then content += "/写"; + cell := table.Cell(i, 2); + cell.Range.Text := content; + cell.Range.Font.NameAscii := "Consolas"; + cell.Range.Font.NameFarEast := "微软雅黑"; + cell.Range.Font.Size := 11; + cell.Range.Font.Apply(); + cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + cell.Range.ParagraphFormat.Apply(); + + r := v["r"] = 2 ? "✅" : "❌"; + cell := table.Cell(i, 3); + cell.Range.Text := r; + cell.Range.Font.NameAscii := "Segoe UI Emoji"; + cell.Range.Font.NameOther := "Segoe UI Emoji"; + cell.Range.Font.NameBi := "Segoe UI Emoji"; + cell.Range.Font.Size := 11; + cell.Range.Font.Apply(); + cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + cell.Range.ParagraphFormat.Apply(); + + font := cell.Range.Font; + w := v["w"] = 2 ? "✅" : "❌"; + cell := table.Cell(i, 4); + cell.Range.Text := w; + cell.Range.Font.NameAscii := "Segoe UI Emoji"; + cell.Range.Font.NameOther := "Segoe UI Emoji"; + cell.Range.Font.NameBi := "Segoe UI Emoji"; + cell.Range.Font.Size := 11; + cell.Range.Font.Apply(); + cell.Range.ParagraphFormat.Alignment := TSDocxEnumerations.wdAlignParagraphCenter(); + cell.Range.ParagraphFormat.Apply(); + i++; + end +End; + +Function FAQ(ActiveDocument); +Begin + ActiveDocument.Paragraphs.Add; + AddTitle(ActiveDocument, "FAQ", 1); + + AddTitle(ActiveDocument, "TSVBA在使用上有哪些特别的地方", 2); + FAQContent(ActiveDocument, "TSVBA重载了[]运算符,对于诸如Documents, Paragraphs, Tables, Borders等,均可用[]获取对应的对象"); + FAQContent(ActiveDocument, "Documents := ActiveDocument.Documents; // 获取Documents对象"); + FAQContent(ActiveDocument, "Document := Documents[2]; // 等价于 Documents.Item(2);"); + + AddTitle(ActiveDocument, "为什么设置了Font, Shading等时未生效", 2); + FAQContent(ActiveDocument, "考虑到性能问题,类似xxx.Range.Font.Size := 10;并不会立即生效,需要手动调用Apply方法,如:"); + FAQContent(ActiveDocument, "paragraph.Range.Font.Name := 'Consolas';"); + FAQContent(ActiveDocument, "paragraph.Range.Font.Size := 12;"); + FAQContent(ActiveDocument, "paragraph.Range.Font.Apply();"); + FAQContent(ActiveDocument, "注意一:在应用Font, Shading, ParagraphFormat, border, ListFormat时均需要执行Apply方法使得设置生效"); + FAQContent(ActiveDocument, "注意二:使用这些类时,最多支持到两级赋值,比如说paragraph.Range.Font中,Range是第一级,paragraph是第二级。若使用paragraphs.Item(1).Range.Font,则不会生效。这里出现了第三级Paragraphs"); + + AddTitle(ActiveDocument, "如何使用VBA中的Enumerations", 2); + FAQContent(ActiveDocument, "用了TSL的Unit特性,将用到的枚举项均封装到了TSDocxEnumerations中"); + FAQContent(ActiveDocument, "Uses TSDocxEnumerations;"); + FAQContent(ActiveDocument, "xxx := TSDocxEnumerations.WdBlack;"); + + AddTitle(ActiveDocument, "为什么目录无法计算页码", 2); + FAQContent(ActiveDocument, "由于目录页码计算比较复杂,目前仅提供生成目录项功能,不支持页码的计算。"); + FAQContent(ActiveDocument, "另外使用TablesOfContents.Add生成目录时,仅支持Range, UpperHeadingLevel, LowerHeadingLevel三个参数的设置,其余参数设置均无效。"); +End; + +Function FAQContent(ActiveDocument, text); +Begin + ActiveDocument.Paragraphs.Add; + para := ActiveDocument.Paragraphs.Last; + para.Range.Text := text; + para.Range.Font.Name := "Consolas"; + para.Range.Font.NameAscii := "Consolas"; + para.Range.Font.NameFarEast := "微软雅黑"; + para.Range.Font.Size := 12; + para.Range.Font.Apply(); + para.Format.CharacterUnitFirstLineIndent := 2; + para.Format.FirstLineIndent := 20; + para.Format.Apply(); +End; + +Function AddTablesOfContents(ActiveDocument); +Begin + range := ActiveDocument.Paragraphs(15).Range; + // println("range.text = {}", range.Text); + range.Collapse(TSDocxEnumerations.wdCollapseStart()); + ActiveDocument.TablesOfContents.Add(Range := range, UseHeadingStyles := true, UpperHeadingLevel := 1, LowerHeadingLevel := 9); +End; + +Function LoadClassInfo(f, methods, properties); +Begin + [err,fh] := io_open(f); + if err then return t; + [err, data] := io_read(fh); + io_close(fh); + if err then return t; + + lines := str2array(string(data), "\n"); + flag := true; + for i:=0 to length(lines)-1 do + begin + line := lines[i]; + if AnsiContainsText(line, "// Methods") then flag := false; + if AnsiContainsText(line, "// Properties") then flag := true; + + if not flag and ParseRegExpr("\\s\+Function\\s\+(\\w+)\\(", line, "i", result, MPos, Mlen) and length(result) then + methods[result[0][1]] := 1; + if AnsiContainsText(line, "property") then + begin + ParseRegExpr("\\s\+property\\s\+(\\w+)\\s\+read\\s\+(\\w+)(\\s\+write\\s\+(\\w+))\?", line, "", result, MPos, Mlen); + if not istable(result) then continue; + rw := array(); + if result[0][2] then rw["r"] := 1; + if result[0][4] then rw["w"] := 1; + properties[result[0][1]] := rw; + end + if AnsiContainsText(line, "End;") then break; + end + for j:=i to length(lines)-1 do + begin + line := lines[j]; + if not AnsiContainsText(line, "Function") then continue; + if ParseRegExpr("Function\\s\+.*\\.(\\w+)\\(", line, "i", result, MPos, Mlen) and istable(result) then + begin + name := result[0][1]; + if not name then continue; + if methods[name] then + begin + methods[name] := 2; + continue; + end + if AnsiContainsText(name, "Read") then + begin + rname := name[5:]; + if properties[rname] then properties[rname]["r"] := 2; + end + else if AnsiContainsText(name, "Write") then + begin + wname := name[6:]; + if properties[wname] then properties[wname]["w"] := 2; + end + end + end +End; + +Function Test(); +Begin + line := "Function TSDocxTables.Add(Range, NumRows, NumColumns, DefaultTableBehavior, AutoFitBehavior);"; + ParseRegExpr("Function\\s\+.*\\.(\\w+)\\(", line, "i", result, MPos, Mlen); + println("result = {}", result); +End; diff --git a/utils/TSVbaBase.tsf b/utils/TSVbaBase.tsf index 7c238d3..ff15540 100644 --- a/utils/TSVbaBase.tsf +++ b/utils/TSVbaBase.tsf @@ -4,9 +4,9 @@ public Function Create(app, cre, par); private - [weakref]application_; - [weakref]parent_; - [autoref]creator_; + application_; + parent_; + creator_; public property Application read ReadApplication;