Type TSDocxCell = Class(TSVbaBase) Uses TSDocxEnumerations; public Function Init(docx, table, r, c);overload; Function Init(node);overload; private Function GetCell(); Function SetCellTcPrWidth(r, c, widthValue, widthType);overload; Function SetCellTcPrWidth(tcpr, widthValue, widthType);overload; Function GetTcprObject(r, c); Function GetTrPrObject(); Function AdjustSameWidth(); Function AdjustFirstColumn(widthValue); Function ProcessWidthValue(widthValue, widthType); private docx_; table_; // TOfficeObj("TTable") tcpr_; // TOfficeObj("TwTcPr") trpr_; // TOfficeObj("TwTrPr") cell_; // TOfficeObj("TCell") min_dxa_width_; // 最小宽度 321 range_; row_; column_; shading_; public // Methods Function AutoSum(); Function Delete(ShiftCells); Function Formula(Formula, NumFormat); Function Merge(MergeTo); Function Select(); Function SetHeight(RowHeight, HeightRule); Function SetWidth(ColumnWidth, RulerStyle); Function Split(NumRows, NumColumns); // Properties property Borders read ReadBorders; property BottomPadding read ReadBottomPadding write WriteBottomPadding; property Column read ReadColumn; property ColumnIndex read ReadColumnIndex; property FitText read ReadFitText write WriteFitText; property Height read ReadHeight write WriteHeight; property HeightRule read ReadHeightRule write WriteHeightRule; property ID read ReadID write WriteID; property LeftPadding read ReadLeftPadding write WriteLeftPadding; property NestingLevel read ReadNestingLevel; property Next read ReadNext; property PreferredWidth read ReadPreferredWidth write WritePreferredWidth; property PreferredWidthType read ReadPreferredWidthType write WritePreferredWidthType; property Previous read ReadPrevious; property Range read ReadRange; property RightPadding read ReadRightPadding write WriteRightPadding; property Row read ReadRow; property RowIndex read ReadRowIndex; property Shading read ReadShading; property Tables read ReadTables; property TopPadding read ReadTopPadding write WriteTopPadding; property VerticalAlignment read ReadVerticalAlignment write WriteVerticalAlignment; property Width read ReadWidth write WriteWidth; property WordWrap read ReadWordWrap write WriteWordWrap; Function WriteWordWrap(value); Function ReadWordWrap(); Function WriteWidth(value); Function ReadWidth(); Function WriteVerticalAlignment(value); Function ReadVerticalAlignment(); Function WriteTopPadding(value); Function ReadTopPadding(); Function ReadTables(index); Function ReadShading(); Function ReadRowIndex(); Function ReadRow(); Function WriteRightPadding(value); Function ReadRightPadding(); Function ReadRange(); Function ReadPrevious(); Function WritePreferredWidthType(value); Function ReadPreferredWidthType(); Function WritePreferredWidth(value); Function ReadPreferredWidth(); Function ReadNext(); Function ReadNestingLevel(); Function WriteLeftPadding(value); Function ReadLeftPadding(); Function WriteID(); Function ReadID(); Function WriteHeightRule(value); Function ReadHeightRule(); Function WriteHeight(value); Function ReadHeight(); Function WriteFitText(); Function ReadFitText(); Function ReadColumnIndex(); Function ReadColumn(); Function WriteBottomPadding(value); Function ReadBottomPadding(); Function ReadBorders(index); End; // ============== 实现 ================= // Function TSDocxCell.Init(docx, table, r, c);overload; Begin docx_ := docx; table_ := table; row_ := r; column_ := c; min_dxa_width_ := 321; tcpr_ := GetTcprObject(row_, column_); trpr_ := nil; // 延迟访问 cell_ := nil; range_ := nil; End; Function TSDocxCell.Init(node);overload; Begin cell_ := TOfficeObj("tcell"); cell_.Create(node); tcpr_node := class(TSXml).GetNode(node, "w:tcPr", "first"); tcpr_ := TOfficeObj("TwTcPr"); tcpr_.InitRootNode(tcpr_node); End; Function TSDocxCell.GetCell(); Begin if ifObj(cell_) then return cell_; cell_ := table_.Cell(row_, column_); return cell_; End; Function TSDocxCell.ProcessWidthValue(widthValue, widthType); Begin case widthType of "dxa": begin widthValue := widthValue * 20; if widthValue < min_dxa_width_ then widthValue := min_dxa_width_; end "pct": begin widthValue := widthValue * 50; end end; End; Function TSDocxCell.GetTrPrObject(); Begin if ifObj(trpr_) then return trpr_; tr_node := class(TSXml).GetNodeN(table_.Root(), "w:tr", column_); trpr_node := tr_node.FirstChild("w:trPr"); if not ifObj(trpr_node) then trpr_node := tr_node.InsertFirstChild("element", "w:trPr"); trpr_:= TOfficeObj("TwTrPr"); trpr_.InitRootNode(trpr_node); return trpr_; End; Function TSDocxCell.SetCellTcPrWidth(r, c, widthValue, widthType);overload; Begin tcpr_obj := GetTcprObject(r, c); if ifnil(tcpr_obj) then return; SetCellTcPrWidth(tcpr_obj, widthValue, widthType); End; Function TSDocxCell.SetCellTcPrWidth(tcpr, widthValue, widthType);overload; Begin ProcessWidthValue(widthValue, widthType); tcpr.Width := widthValue; tcpr.Type := widthType; tcpr.Update(); End; Function TSDocxCell.GetTcprObject(r, c); Begin cell := table_.GetCell(r, c); if ifnil(cell) then return nil; tcpr_node := class(TSXml).GetNode(cell[0], "w:tcPr", "first"); tcpr := TOfficeObj("TwTcPr"); tcpr.InitRootNode(tcpr_node); return tcpr; End; // function Function TSDocxCell.Delete(ShiftCells); Begin if ifnil(ShiftCells) then ShiftCells := TSDocxEnumerations.wdDeleteCellsShiftLeft(); case ShiftCells of TSDocxEnumerations.wdDeleteCellsEntireColumn(): table_.DeleteCell(nil, column_); TSDocxEnumerations.wdDeleteCellsEntireRow(): table_.DeleteCell(row_, nil); TSDocxEnumerations.wdDeleteCellsShiftLeft(): table_.DeleteCell(row_, column_); TSDocxEnumerations.wdDeleteCellsShiftUp(): table_.DeleteCell(row_, column_, 0); end; End; Function TSDocxCell.SetHeight(RowHeight, HeightRule); Begin trpr_obj := GetTrPrObject(); case HeightRule of TSDocxEnumerations.wdRowHeightAtLeast: begin h_rule := "least"; end TSDocxEnumerations.wdRowHeightAuto: begin h_rule := "auto"; end TSDocxEnumerations.wdRowHeightExactly: begin h_rule := "exact"; end end; trpr_obj.Rule := h_rule; trpr_obj.Height := RowHeight * 20; trpr_obj.Update(); End; Function TSDocxCell.SetWidth(ColumnWidth, RulerStyle); Begin if ifnil(RulerStyle) then RulerStyle := TSDocxEnumerations.wdAdjustNone(); width_value := ColumnWidth; case RulerStyle of TSDocxEnumerations.wdAdjustFirstColumn(): AdjustFirstColumn(width_value); TSDocxEnumerations.wdAdjustNone(): begin end TSDocxEnumerations.wdAdjustProportional(): begin end TSDocxEnumerations.wdAdjustSameWidth(): AdjustSameWidth(); end; SetCellTcPrWidth(tcpr_, width_value, "dxa"); End; Function TSDocxCell.AdjustFirstColumn(widthValue); Begin tcpr_next := GetTcprObject(row_, column_ + 1); if not tcpr_next then return; ww := tcpr_next.Value("width"); new_width := ww + tcpr_.Value("width") - widthValue; SetCellTcPrWidth(tcpr_next, new_width, "dxa"); End; Function TSDocxCell.AdjustSameWidth(); Begin if column_ <> table_.Cols() then begin after_total_width := 0; tcpr_arr := array(); for i:=column_+1 to table_.Cols() do begin tcpr := GetTcprObject(row_, i); after_total_width += tcpr.Value("Width"); tcpr_arr[length(tcpr_arr)] := tcpr; end after_width := integer(after_total_width / length(tcpr_arr)); for i:=0 to length(tcpr_arr)-1 do SetCellTcPrWidth(tcpr_arr[i], after_width, "dxa"); end End; Function TSDocxCell.Merge(MergeTo); Begin table_.Merge(self.RowIndex, self.ColumnIndex, MergeTo.RowIndex, MergeTo.ColumnIndex, false); End; // property Function TSDocxCell.ReadColumnIndex(); Begin return column_; End; Function TSDocxCell.ReadColumn(); Begin column_obj := new TSDocxColumn(self.Application, self.Creator, self); column_obj.Init(table_, column_); return column_obj; End; Function TSDocxCell.ReadRowIndex(); Begin return row_; End; // VBA width=100,xml是2000 Function TSDocxCell.WriteWidth(value); Begin width_type := tcpr_.Value("Type"); width_value := value; case width_type of "auto": begin width_value := width_value * 20; width_type := "dxa"; end "dxa": width_value := width_value * 20; "pct": width_value := width_value * 12.05; end; tcpr_.Width := integer(width_value); tcpr_.Type := width_type; tcpr_.Update(); End; Function TSDocxCell.ReadWidth(); Begin width_type := tcpr_.Value("Type"); width_value := tcpr_.Value("width"); case width_type of "dxa", "auto": return width_value / 20; "pct": return width_value / 12.05; end; End; Function TSDocxCell.WriteWordWrap(value); Begin tcpr_.noWrap := value ? 0 : 1; tcpr_.Update(); End; Function TSDocxCell.ReadWordWrap(); Begin return tcpr_.Value("noWrap") ? false : true; End; Function TSDocxCell.WriteVerticalAlignment(value); Begin case value of TSDocxEnumerations.wdCellAlignVerticalBottom(): begin tcpr_.vAlign := "bottom"; tcpr_.Update(); end TSDocxEnumerations.wdCellAlignVerticalCenter(): begin tcpr_.vAlign := "center"; tcpr_.Update(); end TSDocxEnumerations.wdCellAlignVerticalTop(): begin tcpr_.vAlign := "top"; tcpr_.Update(); end; end; End; Function TSDocxCell.ReadVerticalAlignment(); Begin alignment := tcpr_.Value("vAlign"); case alignment of "bottom": return TSDocxEnumerations.wdCellAlignVerticalBottom(); "center": return TSDocxEnumerations.wdCellAlignVerticalCenter(); else return TSDocxEnumerations.wdCellAlignVerticalTop(); end; End; Function TSDocxCell.WriteTopPadding(value); Begin tcpr_.CellMar.Top := 20 * value; tcpr_.CellMar.TopType := "dxa"; tcpr_.Update(); End; Function TSDocxCell.ReadTopPadding(); Begin return tcpr_.CellMar.Value("Top") / 20; End; Function TSDocxCell.WriteLeftPadding(value); Begin tcpr_.CellMar.Left := 20 * value; tcpr_.CellMar.LeftType := "dxa"; tcpr_.Update(); End; Function TSDocxCell.ReadLeftPadding(); Begin return tcpr_.CellMar.Value("Left") / 20; End; Function TSDocxCell.WriteBottomPadding(value); Begin tcpr_.CellMar.Bottom := 20 * value; tcpr_.CellMar.BottomType := "dxa"; tcpr_.Update(); End; Function TSDocxCell.ReadBottomPadding(); Begin return tcpr_.CellMar.Value("Bottom") / 20; End; Function TSDocxCell.WriteRightPadding(value); Begin tcpr_.CellMar.Right := 20 * value; tcpr_.CellMar.RightType := "dxa"; tcpr_.Update(); End; Function TSDocxCell.ReadRightPadding(); Begin return tcpr_.CellMar.Value("Right") / 20; End; Function TSDocxCell.ReadTables(index); Begin tables_obj := new TSDocxTables(self.Application, self.Creator, self); tables_obj.Init(GetCell()); return ifnil(index) ? tables_obj : tables_obj[index]; End; Function TSDocxCell.ReadShading(); Begin 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); Begin borders_obj := new TSDocxBordersCell(self.Application, self.Creator, self); borders_obj.Init(GetCell()); return ifnil(index) ? borders_obj : borders_obj.Item(index); End; Function TSDocxCell.WritePreferredWidthType(value); Begin width_value := nil; width_type := nil; case value of TSDocxEnumerations.wdPreferredWidthAuto(): begin table_.TblPr.Width := 0; table_.TblPr.WidthType := "auto"; table_.TblPr.Update(); width_value := 0; width_type := "auto"; end TSDocxEnumerations.wdPreferredWidthPercent(): begin table_.TblPr.Width := 5000; table_.TblPr.WidthType := "pct"; table_.TblPr.Update(); width_value := integer(5000 / table_.Cols()); width_type := "pct"; end TSDocxEnumerations.wdPreferredWidthPoints(): begin width_value := nil; width_type := "dxa"; end end; SetCellTcPrWidth(row_, column_, width_value, width_type); End; Function TSDocxCell.ReadPreferredWidthType(); Begin width_type := tcpr_.Value("Type"); case width_type of "auto": return TSDocxEnumerations.wdPreferredWidthAuto(); "dxa": return TSDocxEnumerations.wdPreferredWidthPoints(); "pct": return TSDocxEnumerations.wdPreferredWidthPercent(); end; End; Function TSDocxCell.WritePreferredWidth(value); Begin width_type := self.PreferredWidthType; width_value := value; case width_type of TSDocxEnumerations.wdPreferredWidthAuto(), TSDocxEnumerations.wdPreferredWidthPoints(): begin width_type := "dxa"; SetCellTcPrWidth(row_, column_, width_value, width_type); end TSDocxEnumerations.wdPreferredWidthPercent(): begin width_type := "pct"; SetCellTcPrWidth(row_, column_, width_value, width_type); end end; End; Function TSDocxCell.ReadPreferredWidth(); Begin width_type := tcpr_.Value("Type"); width_value := tcpr_.Value("Width"); case width_type of "auto", "dxa": return width_value / 20; "pct": return width_value / 50; end; End; Function TSDocxCell.WriteHeight(value); Begin SetHeight(value, self.HeightRule); End; Function TSDocxCell.ReadHeight(); Begin trpr_obj := GetTrPrObject(); value := trpr_obj.Value("Height"); return ifnil(value) ? 0 : value / 20; End; Function TSDocxCell.WriteHeightRule(value); Begin trpr_obj := GetTrPrObject(); case value of TSDocxEnumerations.wdRowHeightAuto(): trpr_obj.Rule := "auto"; TSDocxEnumerations.wdRowHeightAtLeast(): trpr_obj.Rule := "least"; TSDocxEnumerations.wdRowHeightExactly(): trpr_obj.Rule := "exact"; end; trpr_obj.Update(); End; Function TSDocxCell.ReadHeightRule(); Begin trpr_obj := GetTrPrObject(); rule := trpr_obj.Value("Rule"); case rule of "auto": return TSDocxEnumerations.wdRowHeightAuto(); "least": return TSDocxEnumerations.wdRowHeightAtLeast(); "exact": return TSDocxEnumerations.wdRowHeightExactly(); end; return TSDocxEnumerations.wdRowHeightAtLeast(); End; Function TSDocxCell.ReadNext(); Begin if column_ = table_.Cols() then begin if row_ = table_.Rows() then return nil; return self.Parent.Cell(row_ + 1, 1); end return self.Parent.Cell(row_, column_ + 1); End; Function TSDocxCell.ReadPrevious(); Begin if column_ = 1 then begin if row_ = 1 then return nil; return self.Parent.Cell(row_ - 1, table_.Cols()); end return self.Parent.Cell(row_, column_ - 1); End; Function TSDocxCell.ReadRange(); Begin if ifnil(range_) then begin obj := new TSWdRange(docx_.Body().Root(), GetCell().Root()); range_ := new TSDocxRange(self.Application, self.Creator, self); range_.Init(docx_, obj); end return range_; End;