You've already forked lazarus-ccr
fpspreadsheet: Add support for diagonal border lines. Implemented for BIFF8 and ods (BIFF2 and 5 do not support diagonal borders, OOXML reader currently does not have border support). Test cases adapted. "spready" adapted to show diagonal borders.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3400 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -44,9 +44,6 @@
|
||||
<UseExternalDbgSyms Value="True"/>
|
||||
</Debugging>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
</Item2>
|
||||
<Item3 Name="Release">
|
||||
@ -74,9 +71,6 @@
|
||||
</Debugging>
|
||||
<LinkSmart Value="True"/>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
</Item3>
|
||||
</BuildModes>
|
||||
@ -109,7 +103,6 @@
|
||||
<PathDelim Value="\"/>
|
||||
<SearchPaths>
|
||||
<OtherUnitFiles Value=".."/>
|
||||
<SrcPath Value=".."/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
<SyntaxOptions>
|
||||
@ -121,8 +114,5 @@
|
||||
<DebugInfoType Value="dsDwarf2Set"/>
|
||||
</Debugging>
|
||||
</Linking>
|
||||
<Other>
|
||||
<CompilerPath Value="$(CompPath)"/>
|
||||
</Other>
|
||||
</CompilerOptions>
|
||||
</CONFIG>
|
||||
|
@ -95,12 +95,15 @@ begin
|
||||
MyWorksheet.WriteBorderLineStyle(5, 7, cbWest, lsMedium);
|
||||
MyWorksheet.WriteBorderLineStyle(5, 7, cbNorth, lsMedium);
|
||||
|
||||
// J6 empty cell, all thick borders
|
||||
MyWorksheet.WriteBorders(5, 9, [cbNorth, cbEast, cbSouth, cbWest]);
|
||||
// J6 empty cell, all thick borders, diagonals thin&red
|
||||
MyWorksheet.WriteBorders(5, 9, [cbNorth, cbEast, cbSouth, cbWest, cbDiagUp, cbDiagDown]);
|
||||
MyWorksheet.WriteBorderLineStyle(5, 9, cbSouth, lsThick);
|
||||
MyWorksheet.WriteBorderLineStyle(5, 9, cbEast, lsThick);
|
||||
MyWorksheet.WriteBorderLineStyle(5, 9, cbWest, lsThick);
|
||||
MyWorksheet.WriteBorderLineStyle(5, 9, cbNorth, lsThick);
|
||||
MyWorksheet.WriteBorderLineStyle(5, 9, cbDiagUp, lsThin);
|
||||
MyWorksheet.WriteBorderLineStyle(5, 9, cbDiagDown, lsThin);
|
||||
MyWorksheet.WriteBorderColor(5, 9, cbDiagUp, scRed);
|
||||
|
||||
// K6 empty cell, top border thick
|
||||
MyWorksheet.WriteBorders(5, 11, [cbNorth]);
|
||||
|
@ -2172,6 +2172,16 @@ begin
|
||||
Include(borders, cbWest);
|
||||
SetBorderStyle(cbWest, s);
|
||||
end;
|
||||
s := GetAttrValue(styleChildNode, 'style:diagonal-bl-tr');
|
||||
if (s <> '') and (s <> 'none') then begin
|
||||
Include(borders, cbDiagUp);
|
||||
SetBorderStyle(cbDiagUp, s);
|
||||
end;
|
||||
s := GetAttrValue(styleChildNode, 'style:diagonal-tl-br');
|
||||
if (s <> '') and (s <>'none') then begin
|
||||
Include(borders, cbDiagDown);
|
||||
SetBorderStyle(cbDiagDown, s);
|
||||
end;
|
||||
|
||||
// Text wrap
|
||||
s := GetAttrValue(styleChildNode, 'fo:wrap-option');
|
||||
@ -3292,6 +3302,24 @@ begin
|
||||
Result := Result + 'style:border-linewidth-top="0.002cm 0.035cm 0.002cm" ';
|
||||
end else
|
||||
Result := Result + 'fo:border-top="none" ';
|
||||
|
||||
if cbDiagUp in AFormat.Border then begin
|
||||
Result := Result + Format('style:diagonal-bl-tr="%s %s %s" ', [
|
||||
BORDER_LINEWIDTHS[AFormat.BorderStyles[cbDiagUp].LineStyle],
|
||||
BORDER_LINESTYLES[AFormat.BorderStyles[cbDiagUp].LineStyle],
|
||||
Workbook.GetPaletteColorAsHTMLStr(AFormat.BorderStyles[cbDiagUp].Color)
|
||||
]);
|
||||
end;
|
||||
|
||||
if cbDiagDown in AFormat.Border then begin
|
||||
Result := Result + Format('style:diagonal-tl-br="%s %s %s" ', [
|
||||
BORDER_LINEWIDTHS[AFormat.BorderStyles[cbDiagDown].LineStyle],
|
||||
BORDER_LINESTYLES[AFormat.BorderStyles[cbDiagDown].LineStyle],
|
||||
Workbook.GetPaletteColorAsHTMLStr(AFormat.BorderStyles[cbDiagDown].Color)
|
||||
]);
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
function TsSpreadOpenDocWriter.WriteDefaultFontXMLAsString: String;
|
||||
|
@ -342,7 +342,7 @@ type
|
||||
|
||||
{@@ Indicates the border for a cell. If included in the CellBorders set the
|
||||
corresponding border is drawn in the style defined by the CellBorderStyle. }
|
||||
TsCellBorder = (cbNorth, cbWest, cbEast, cbSouth);
|
||||
TsCellBorder = (cbNorth, cbWest, cbEast, cbSouth, cbDiagUp, cbDiagDown);
|
||||
|
||||
{@@ Indicates the border for a cell }
|
||||
TsCellBorders = set of TsCellBorder;
|
||||
@ -363,6 +363,8 @@ type
|
||||
{@@ Border styles for each cell border used by default: a thin, black, solid line }
|
||||
const
|
||||
DEFAULT_BORDERSTYLES: TsCellBorderStyles = (
|
||||
(LineStyle: lsThin; Color: scBlack),
|
||||
(LineStyle: lsThin; Color: scBlack),
|
||||
(LineStyle: lsThin; Color: scBlack),
|
||||
(LineStyle: lsThin; Color: scBlack),
|
||||
(LineStyle: lsThin; Color: scBlack),
|
||||
|
@ -1071,8 +1071,13 @@ end;
|
||||
@param ARect Rectangle in pixels occupied by the cell.
|
||||
}
|
||||
procedure TsCustomWorksheetGrid.DrawCellBorders(ACol, ARow: Integer; ARect: TRect);
|
||||
const
|
||||
drawHor = 0;
|
||||
drawVert = 1;
|
||||
drawDiagUp = 2;
|
||||
drawDiagDown = 3;
|
||||
|
||||
procedure DrawBorderLine(ACoord: Integer; ARect: TRect; IsHor: Boolean;
|
||||
procedure DrawBorderLine(ACoord: Integer; ARect: TRect; ADrawDirection: Byte;
|
||||
ABorderStyle: TsCellBorderStyle);
|
||||
const
|
||||
// TsLineStyle = (lsThin, lsMedium, lsDashed, lsDotted, lsThick, lsDouble, lsHair);
|
||||
@ -1082,6 +1087,8 @@ procedure TsCustomWorksheetGrid.DrawCellBorders(ACol, ARow: Integer; ARect: TRec
|
||||
(1, 2, 1, 1, 3, 1, 1);
|
||||
var
|
||||
width3: Boolean; // line is 3 pixels wide
|
||||
deltax, deltay: Integer;
|
||||
angle: Double;
|
||||
begin
|
||||
Canvas.Pen.Style := PEN_STYLES[ABorderStyle.LineStyle];
|
||||
Canvas.Pen.Width := PEN_WIDTHS[ABorderStyle.LineStyle];
|
||||
@ -1089,66 +1096,124 @@ procedure TsCustomWorksheetGrid.DrawCellBorders(ACol, ARow: Integer; ARect: TRec
|
||||
Canvas.Pen.EndCap := pecSquare;
|
||||
width3 := (ABorderStyle.LineStyle in [lsThick, lsDouble]);
|
||||
|
||||
// Workaround until efficient drawing procedures for diagonal "hair" lines
|
||||
// is available
|
||||
if (ADrawDirection in [drawDiagUp, drawDiagDown]) and
|
||||
(ABorderStyle.LineStyle = lsHair)
|
||||
then
|
||||
ABorderStyle.LineStyle := lsDotted;
|
||||
|
||||
// Tuning the rectangle to avoid issues at the grid borders and to get nice corners
|
||||
if (ABorderStyle.LineStyle in [lsMedium, lsThick, lsDouble]) then begin
|
||||
if ACol = ColCount-1 then begin
|
||||
if not IsHor and (ACoord = ARect.Right-1) and width3 then dec(ACoord);
|
||||
if (ADrawDirection = drawVert) and (ACoord = ARect.Right-1) and width3
|
||||
then dec(ACoord);
|
||||
dec(ARect.Right);
|
||||
end;
|
||||
if ARow = RowCount-1 then begin
|
||||
if IsHor and (ACoord = ARect.Bottom-1) and width3 then dec(ACoord);
|
||||
if (ADrawDirection = drawHor) and (ACoord = ARect.Bottom-1) and width3
|
||||
then dec(ACoord);
|
||||
dec(ARect.Bottom);
|
||||
end;
|
||||
end;
|
||||
if ABorderStyle.LineStyle in [lsMedium, lsThick] then begin
|
||||
if IsHor then dec(ARect.Right, 1) else dec(ARect.Bottom, 1);
|
||||
if (ADrawDirection = drawHor) then
|
||||
dec(ARect.Right, 1)
|
||||
else if (ADrawDirection = drawVert) then
|
||||
dec(ARect.Bottom, 1);
|
||||
end;
|
||||
|
||||
// Painting
|
||||
case ABorderStyle.LineStyle of
|
||||
lsThin, lsMedium, lsThick, lsDotted, lsDashed:
|
||||
if IsHor then
|
||||
Canvas.Line(ARect.Left, ACoord, ARect.Right, ACoord)
|
||||
else
|
||||
Canvas.Line(ACoord, ARect.Top, ACoord, ARect.Bottom);
|
||||
case ADrawDirection of
|
||||
drawHor : Canvas.Line(ARect.Left, ACoord, ARect.Right, ACoord);
|
||||
drawVert : Canvas.Line(ACoord, ARect.Top, ACoord, ARect.Bottom);
|
||||
drawDiagUp : Canvas.Line(ARect.Left, ARect.Bottom, ARect.Right, ARect.Top);
|
||||
drawDiagDown: Canvas.Line(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
|
||||
end;
|
||||
|
||||
lsHair:
|
||||
if IsHor then
|
||||
DrawHairLineHor(Canvas, ARect.Left, ARect.Right, ACoord)
|
||||
else
|
||||
DrawHairLineVert(Canvas, ACoord, ARect.Top, ARect.Bottom);
|
||||
case ADrawDirection of
|
||||
drawHor : DrawHairLineHor(Canvas, ARect.Left, ARect.Right, ACoord);
|
||||
drawVert : DrawHairLineVert(Canvas, ACoord, ARect.Top, ARect.Bottom);
|
||||
drawDiagUp : ;
|
||||
drawDiagDown: ;
|
||||
end;
|
||||
|
||||
lsDouble:
|
||||
if IsHor then begin
|
||||
Canvas.Line(ARect.Left, ACoord-1, ARect.Right, ACoord-1);
|
||||
Canvas.Line(ARect.Left, ACoord+1, ARect.Right, ACoord+1);
|
||||
Canvas.Pen.Color := Color;
|
||||
Canvas.Line(ARect.Left, ACoord, ARect.Right, ACoord);
|
||||
end else begin
|
||||
Canvas.Line(ACoord-1, ARect.Top, ACoord-1, ARect.Bottom);
|
||||
Canvas.Line(ACoord+1, ARect.Top, ACoord+1, ARect.Bottom);
|
||||
Canvas.Pen.Color := Color;
|
||||
Canvas.Line(ACoord, ARect.Top, ACoord, ARect.Bottom);
|
||||
case ADrawDirection of
|
||||
drawHor:
|
||||
begin
|
||||
Canvas.Line(ARect.Left, ACoord-1, ARect.Right, ACoord-1);
|
||||
Canvas.Line(ARect.Left, ACoord+1, ARect.Right, ACoord+1);
|
||||
Canvas.Pen.Color := Color;
|
||||
Canvas.Line(ARect.Left, ACoord, ARect.Right, ACoord);
|
||||
end;
|
||||
drawVert:
|
||||
begin
|
||||
Canvas.Line(ACoord-1, ARect.Top, ACoord-1, ARect.Bottom);
|
||||
Canvas.Line(ACoord+1, ARect.Top, ACoord+1, ARect.Bottom);
|
||||
Canvas.Pen.Color := Color;
|
||||
Canvas.Line(ACoord, ARect.Top, ACoord, ARect.Bottom);
|
||||
end;
|
||||
drawDiagUp:
|
||||
begin
|
||||
if ARect.Right = ARect.Left then
|
||||
angle := pi/2
|
||||
else
|
||||
angle := arctan((ARect.Bottom-ARect.Top) / (ARect.Right-ARect.Left));
|
||||
deltax := Max(1, round(1.0 / sin(angle)));
|
||||
deltay := Max(1, round(1.0 / cos(angle)));
|
||||
Canvas.Line(ARect.Left, ARect.Bottom-deltay-1, ARect.Right-deltax, ARect.Top-1);
|
||||
Canvas.Line(ARect.Left+deltax, ARect.Bottom-1, ARect.Right, ARect.Top+deltay-1);
|
||||
end;
|
||||
drawDiagDown:
|
||||
begin
|
||||
if ARect.Right = ARect.Left then
|
||||
angle := pi/2
|
||||
else
|
||||
angle := arctan((ARect.Bottom-ARect.Top) / (ARect.Right-ARect.Left));
|
||||
deltax := Max(1, round(1.0 / sin(angle)));
|
||||
deltay := Max(1, round(1.0 / cos(angle)));
|
||||
Canvas.Line(ARect.Left, ARect.Top+deltay-1, ARect.Right-deltax, ARect.Bottom-1);
|
||||
Canvas.Line(ARect.Left+deltax, ARect.Top-1, ARect.Right, ARect.Bottom-deltay-1);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
bs: TsCellBorderStyle;
|
||||
cell: PCell;
|
||||
begin
|
||||
if Assigned(FWorksheet) then begin
|
||||
// Left border
|
||||
if GetBorderStyle(ACol, ARow, -1, 0, bs) then
|
||||
DrawBorderLine(ARect.Left-1, ARect, false, bs);
|
||||
DrawBorderLine(ARect.Left-1, ARect, drawVert, bs);
|
||||
// Right border
|
||||
if GetBorderStyle(ACol, ARow, +1, 0, bs) then
|
||||
DrawBorderLine(ARect.Right-1, ARect, false, bs);
|
||||
DrawBorderLine(ARect.Right-1, ARect, drawVert, bs);
|
||||
// Top border
|
||||
if GetBorderstyle(ACol, ARow, 0, -1, bs) then
|
||||
DrawBorderLine(ARect.Top-1, ARect, true, bs);
|
||||
DrawBorderLine(ARect.Top-1, ARect, drawHor, bs);
|
||||
// Bottom border
|
||||
if GetBorderStyle(ACol, ARow, 0, +1, bs) then
|
||||
DrawBorderLine(ARect.Bottom-1, ARect, true, bs);
|
||||
DrawBorderLine(ARect.Bottom-1, ARect, drawHor, bs);
|
||||
|
||||
cell := FWorksheet.FindCell(ARow-FHeaderCount, ACol-FHeaderCount);
|
||||
if cell <> nil then begin
|
||||
// Diagonal up
|
||||
if cbDiagUp in cell^.Border then begin
|
||||
bs := cell^.Borderstyles[cbDiagUp];
|
||||
DrawBorderLine(0, ARect, drawDiagUp, bs);
|
||||
end;
|
||||
// Diagonal down
|
||||
if cbDiagDown in cell^.Border then begin
|
||||
bs := cell^.BorderStyles[cbDiagDown];
|
||||
DrawborderLine(0, ARect, drawDiagDown, bs);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -1977,7 +2042,10 @@ begin
|
||||
r := GetWorksheetRow(ARow);
|
||||
c := GetWorksheetCol(ACol);
|
||||
cell := FWorksheet.FindCell(r, c);
|
||||
neighborcell := FWorksheet.FindCell(r+ADeltaRow, c+ADeltaCol);
|
||||
if (r+ADeltaRow < 0) or (c + ADeltaCol < 0) then
|
||||
neighborcell := nil
|
||||
else
|
||||
neighborcell := FWorksheet.FindCell(r+ADeltaRow, c+ADeltaCol);
|
||||
// Only cell has border, but neighbor has not
|
||||
if ((cell <> nil) and (border in cell^.Border)) and
|
||||
((neighborcell = nil) or (neighborborder in neighborcell^.Border))
|
||||
|
@ -35,88 +35,88 @@ This package is all you need if you don't want graphical components (like grids
|
||||
<UnitName Value="fpsallformats"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Filename Value="fpsopendocument.pas"/>
|
||||
<UnitName Value="fpsopendocument"/>
|
||||
</Item3>
|
||||
<Item4>
|
||||
<Filename Value="fpspreadsheet.pas"/>
|
||||
<UnitName Value="fpspreadsheet"/>
|
||||
</Item4>
|
||||
<Item5>
|
||||
<Filename Value="xlsbiff2.pas"/>
|
||||
<UnitName Value="xlsbiff2"/>
|
||||
</Item5>
|
||||
<Item6>
|
||||
<Filename Value="xlsbiff5.pas"/>
|
||||
<UnitName Value="xlsbiff5"/>
|
||||
</Item6>
|
||||
<Item7>
|
||||
<Filename Value="xlsbiff8.pas"/>
|
||||
<UnitName Value="xlsbiff8"/>
|
||||
</Item7>
|
||||
<Item8>
|
||||
<Filename Value="xlsxooxml.pas"/>
|
||||
<UnitName Value="xlsxooxml"/>
|
||||
</Item8>
|
||||
<Item9>
|
||||
<Filename Value="fpsutils.pas"/>
|
||||
<UnitName Value="fpsutils"/>
|
||||
</Item9>
|
||||
<Item10>
|
||||
<Filename Value="fpsstreams.pas"/>
|
||||
<UnitName Value="fpsStreams"/>
|
||||
</Item10>
|
||||
<Item11>
|
||||
<Filename Value="fpszipper.pp"/>
|
||||
<UnitName Value="fpszipper"/>
|
||||
</Item11>
|
||||
<Item12>
|
||||
<Filename Value="uvirtuallayer_types.pas"/>
|
||||
<UnitName Value="uvirtuallayer_types"/>
|
||||
</Item12>
|
||||
<Item13>
|
||||
<Filename Value="uvirtuallayer.pas"/>
|
||||
<UnitName Value="uvirtuallayer"/>
|
||||
</Item13>
|
||||
<Item14>
|
||||
<Filename Value="uvirtuallayer_ole.pas"/>
|
||||
<UnitName Value="uvirtuallayer_ole"/>
|
||||
</Item14>
|
||||
<Item15>
|
||||
<Filename Value="uvirtuallayer_ole_helpers.pas"/>
|
||||
<UnitName Value="uvirtuallayer_ole_helpers"/>
|
||||
</Item15>
|
||||
<Item16>
|
||||
<Filename Value="uvirtuallayer_ole_types.pas"/>
|
||||
<UnitName Value="uvirtuallayer_ole_types"/>
|
||||
</Item16>
|
||||
<Item17>
|
||||
<Filename Value="uvirtuallayer_stream.pas"/>
|
||||
<UnitName Value="uvirtuallayer_stream"/>
|
||||
</Item17>
|
||||
<Item18>
|
||||
<Filename Value="fpolebasic.pas"/>
|
||||
<UnitName Value="fpolebasic"/>
|
||||
</Item18>
|
||||
<Item19>
|
||||
<Filename Value="xlscommon.pas"/>
|
||||
<UnitName Value="xlscommon"/>
|
||||
</Item19>
|
||||
<Item20>
|
||||
<Filename Value="wikitable.pas"/>
|
||||
<UnitName Value="wikitable"/>
|
||||
</Item20>
|
||||
<Item21>
|
||||
<Filename Value="fpsnumformatparser.pas"/>
|
||||
<UnitName Value="fpsNumFormatParser"/>
|
||||
</Item21>
|
||||
<Item22>
|
||||
<Filename Value="fpsfunc.pas"/>
|
||||
<UnitName Value="fpsfunc"/>
|
||||
</Item22>
|
||||
<Item23>
|
||||
</Item3>
|
||||
<Item4>
|
||||
<Filename Value="fpsstreams.pas"/>
|
||||
<UnitName Value="fpsStreams"/>
|
||||
</Item4>
|
||||
<Item5>
|
||||
<Filename Value="fpspreadsheet.pas"/>
|
||||
<UnitName Value="fpspreadsheet"/>
|
||||
</Item5>
|
||||
<Item6>
|
||||
<Filename Value="fpsxmlcommon.pas"/>
|
||||
<UnitName Value="fpsxmlcommon"/>
|
||||
</Item6>
|
||||
<Item7>
|
||||
<Filename Value="xlsbiff2.pas"/>
|
||||
<UnitName Value="xlsbiff2"/>
|
||||
</Item7>
|
||||
<Item8>
|
||||
<Filename Value="xlsbiff5.pas"/>
|
||||
<UnitName Value="xlsbiff5"/>
|
||||
</Item8>
|
||||
<Item9>
|
||||
<Filename Value="xlsbiff8.pas"/>
|
||||
<UnitName Value="xlsbiff8"/>
|
||||
</Item9>
|
||||
<Item10>
|
||||
<Filename Value="xlsxooxml.pas"/>
|
||||
<UnitName Value="xlsxooxml"/>
|
||||
</Item10>
|
||||
<Item11>
|
||||
<Filename Value="fpsopendocument.pas"/>
|
||||
<UnitName Value="fpsopendocument"/>
|
||||
</Item11>
|
||||
<Item12>
|
||||
<Filename Value="fpsutils.pas"/>
|
||||
<UnitName Value="fpsutils"/>
|
||||
</Item12>
|
||||
<Item13>
|
||||
<Filename Value="fpszipper.pp"/>
|
||||
<UnitName Value="fpszipper"/>
|
||||
</Item13>
|
||||
<Item14>
|
||||
<Filename Value="uvirtuallayer_types.pas"/>
|
||||
<UnitName Value="uvirtuallayer_types"/>
|
||||
</Item14>
|
||||
<Item15>
|
||||
<Filename Value="uvirtuallayer.pas"/>
|
||||
<UnitName Value="uvirtuallayer"/>
|
||||
</Item15>
|
||||
<Item16>
|
||||
<Filename Value="uvirtuallayer_ole.pas"/>
|
||||
<UnitName Value="uvirtuallayer_ole"/>
|
||||
</Item16>
|
||||
<Item17>
|
||||
<Filename Value="uvirtuallayer_ole_helpers.pas"/>
|
||||
<UnitName Value="uvirtuallayer_ole_helpers"/>
|
||||
</Item17>
|
||||
<Item18>
|
||||
<Filename Value="uvirtuallayer_ole_types.pas"/>
|
||||
<UnitName Value="uvirtuallayer_ole_types"/>
|
||||
</Item18>
|
||||
<Item19>
|
||||
<Filename Value="uvirtuallayer_stream.pas"/>
|
||||
<UnitName Value="uvirtuallayer_stream"/>
|
||||
</Item19>
|
||||
<Item20>
|
||||
<Filename Value="fpolebasic.pas"/>
|
||||
<UnitName Value="fpolebasic"/>
|
||||
</Item20>
|
||||
<Item21>
|
||||
<Filename Value="wikitable.pas"/>
|
||||
<UnitName Value="wikitable"/>
|
||||
</Item21>
|
||||
<Item22>
|
||||
<Filename Value="fpsnumformatparser.pas"/>
|
||||
<UnitName Value="fpsNumFormatParser"/>
|
||||
</Item22>
|
||||
<Item23>
|
||||
<Filename Value="fpsfunc.pas"/>
|
||||
<UnitName Value="fpsfunc"/>
|
||||
</Item23>
|
||||
</Files>
|
||||
<RequiredPkgs Count="2">
|
||||
|
@ -7,11 +7,11 @@ unit laz_fpspreadsheet;
|
||||
interface
|
||||
|
||||
uses
|
||||
fpolestorage, fpsallformats, fpsopendocument, fpspreadsheet, xlsbiff2,
|
||||
xlsbiff5, xlsbiff8, xlsxooxml, fpsutils, fpsStreams, fpszipper,
|
||||
uvirtuallayer_types, uvirtuallayer, uvirtuallayer_ole,
|
||||
fpolestorage, fpsallformats, xlscommon, fpsStreams, fpspreadsheet,
|
||||
fpsxmlcommon, xlsbiff2, xlsbiff5, xlsbiff8, xlsxooxml, fpsopendocument,
|
||||
fpsutils, fpszipper, uvirtuallayer_types, uvirtuallayer, uvirtuallayer_ole,
|
||||
uvirtuallayer_ole_helpers, uvirtuallayer_ole_types, uvirtuallayer_stream,
|
||||
fpolebasic, xlscommon, wikitable, fpsNumFormatParser, fpsfunc, fpsxmlcommon;
|
||||
fpolebasic, wikitable, fpsNumFormatParser, fpsfunc;
|
||||
|
||||
implementation
|
||||
|
||||
|
@ -34,7 +34,7 @@ var
|
||||
|
||||
SollColWidths: array[0..1] of Single;
|
||||
SollRowHeights: Array[0..2] of Single;
|
||||
SollBorders: array[0..15] of TsCellBorders;
|
||||
SollBorders: array[0..19] of TsCellBorders;
|
||||
SollBorderLineStyles: array[0..6] of TsLineStyle;
|
||||
SollBorderColors: array[0..5] of TsColor;
|
||||
|
||||
@ -245,15 +245,19 @@ begin
|
||||
SollBorders[12] := [cbEast, cbSouth, cbNorth];
|
||||
SollBorders[13] := [cbSouth, cbWest, cbNorth];
|
||||
SollBorders[14] := [cbWest, cbNorth, cbEast];
|
||||
SollBorders[15] := [cbEast, cbSouth, cbWest, cbNorth];
|
||||
SollBorders[15] := [cbEast, cbSouth, cbWest, cbNorth]; // BIFF2/5 end here
|
||||
SollBorders[16] := [cbDiagUp];
|
||||
SollBorders[17] := [cbDiagDown];
|
||||
SollBorders[18] := [cbDiagUp, cbDiagDown];
|
||||
SollBorders[19] := [cbEast, cbSouth, cbWest, cbNorth, cbDiagUp, cbDiagDown];
|
||||
|
||||
SollBorderLineStyles[0] := lsThin;
|
||||
SollBorderLineStyles[1] := lsMedium;
|
||||
SollBorderLineStyles[2] := lsThick;
|
||||
SollBorderLineStyles[3] := lsThick;
|
||||
SollBorderLineStyles[4] := lsDashed;
|
||||
SollBorderLineStyles[5] := lsDotted;
|
||||
SollBorderLineStyles[6] := lsDouble;
|
||||
SollBorderLineStyles[3] := lsDashed;
|
||||
SollBorderLineStyles[4] := lsDotted;
|
||||
SollBorderLineStyles[5] := lsDouble;
|
||||
SollBorderLineStyles[6] := lsHair;
|
||||
|
||||
SollBorderColors[0] := scBlue;
|
||||
SollBorderColors[1] := scRed;
|
||||
@ -569,7 +573,7 @@ var
|
||||
MyWorksheet: TsWorksheet;
|
||||
MyWorkbook: TsWorkbook;
|
||||
MyCell: PCell;
|
||||
col: Integer;
|
||||
col, maxCol: Integer;
|
||||
expected: String;
|
||||
current: String;
|
||||
TempFile: string; //write xls/xml to this file and read back from it
|
||||
@ -581,7 +585,11 @@ begin
|
||||
// Write out all test values
|
||||
MyWorkbook := TsWorkbook.Create;
|
||||
MyWorkSheet:= MyWorkBook.AddWorksheet(BordersSheet);
|
||||
for col := Low(SollBorders) to High(SollBorders) do
|
||||
if AFormat in [sfExcel2, sfExcel5] then
|
||||
maxCol := 15 // no diagonal border support in BIFF2 and BIFF5
|
||||
else
|
||||
maxCol := High(SollBorders);
|
||||
for col := Low(SollBorders) to maxCol do
|
||||
begin
|
||||
MyWorksheet.WriteUsedFormatting(row, col, [uffBorder]);
|
||||
MyCell := MyWorksheet.GetCell(row, col);
|
||||
@ -656,6 +664,9 @@ var
|
||||
current: Integer;
|
||||
TempFile: string; //write xls/xml to this file and read back from it
|
||||
c, ls: Integer;
|
||||
borders: TsCellBorders;
|
||||
diagUp_ls: Integer;
|
||||
diagUp_clr: integer;
|
||||
begin
|
||||
{// Not needed: use workbook.writetofile with overwrite=true
|
||||
if fileexists(TempFile) then
|
||||
@ -665,14 +676,18 @@ begin
|
||||
MyWorkbook := TsWorkbook.Create;
|
||||
MyWorkSheet:= MyWorkBook.AddWorksheet(BordersSheet);
|
||||
|
||||
borders := [cbNorth, cbSouth, cbEast, cbWest];
|
||||
if AFormat in [sfExcel8, sfOpenDocument, sfOOXML] then
|
||||
borders := borders + [cbDiagUp, cbDiagDown];
|
||||
|
||||
c := 0;
|
||||
ls := 0;
|
||||
for row := 1 to 10 do
|
||||
begin
|
||||
for col := 1 to 10 do
|
||||
begin
|
||||
MyWorksheet.WriteBorders(row*2, col*2, [cbNorth, cbSouth, cbEast, cbWest]);
|
||||
for b in TsCellBorders do
|
||||
MyWorksheet.WriteBorders(row*2, col*2, borders);
|
||||
for b in borders do
|
||||
begin
|
||||
MyWorksheet.WriteBorderLineStyle(row*2, col*2, b, SollBorderLineStyles[ls]);
|
||||
MyWorksheet.WriteBorderColor(row*2, col*2, b, SollBorderColors[c]);
|
||||
@ -709,14 +724,30 @@ begin
|
||||
MyCell := MyWorksheet.FindCell(row*2, col*2);
|
||||
if myCell = nil then
|
||||
fail('Error in test code. Failed to get cell.');
|
||||
for b in TsCellBorder do
|
||||
for b in borders do
|
||||
begin
|
||||
current := ord(MyCell^.BorderStyles[b].LineStyle);
|
||||
// In Excel both diagonals have the same line style. The reader picks
|
||||
// the line style of the "diagonal-up" border. We use this as expected
|
||||
// value in the "diagonal-down" case.
|
||||
expected := ord(SollBorderLineStyles[ls]);
|
||||
if AFormat in [sfExcel8, sfOOXML] then
|
||||
case b of
|
||||
cbDiagUp : diagUp_ls := expected;
|
||||
cbDiagDown: expected := diagUp_ls;
|
||||
end;
|
||||
CheckEquals(expected, current,
|
||||
'Test saved border line style mismatch, cell ' + CellNotation(MyWorksheet, row*2, col*2));
|
||||
current := MyCell^.BorderStyles[b].Color;
|
||||
expected := SollBorderColors[c];
|
||||
// In Excel both diagonals have the same line color. The reader picks
|
||||
// the color of the "diagonal-up" border. We use this as expected value
|
||||
// in the "diagonal-down" case.
|
||||
if AFormat in [sfExcel8, sfOOXML] then
|
||||
case b of
|
||||
cbDiagUp : diagUp_clr := expected;
|
||||
cbDiagDown: expected := diagUp_clr;
|
||||
end;
|
||||
CheckEquals(expected, current,
|
||||
'Test saved border color mismatch, cell ' + CellNotation(MyWorksheet, row*2, col*2));
|
||||
inc(ls);
|
||||
|
@ -257,12 +257,17 @@ const
|
||||
MASK_XF_BORDER_RIGHT = $000000F0;
|
||||
MASK_XF_BORDER_TOP = $00000F00;
|
||||
MASK_XF_BORDER_BOTTOM = $0000F000;
|
||||
MASK_XF_BORDER_DIAGONAL = $01E00000;
|
||||
|
||||
MASK_XF_BORDER_SHOW_DIAGONAL_DOWN = $40000000;
|
||||
MASK_XF_BORDER_SHOW_DIAGONAL_UP = $80000000;
|
||||
|
||||
{ XF CELL BORDER COLORS }
|
||||
MASK_XF_BORDER_LEFT_COLOR = $007F0000;
|
||||
MASK_XF_BORDER_RIGHT_COLOR = $3F800000;
|
||||
MASK_XF_BORDER_TOP_COLOR = $0000007F;
|
||||
MASK_XF_BORDER_BOTTOM_COLOR = $00003F80;
|
||||
MASK_XF_BORDER_DIAGONAL_COLOR = $001FC000;
|
||||
|
||||
{ XF CELL BACKGROUND PATTERN }
|
||||
MASK_XF_BACKGROUND_PATTERN = $FC000000;
|
||||
@ -1214,11 +1219,21 @@ begin
|
||||
XFBorderDWord1 := XFBorderDWord1 or ((ord(ABorderStyles[cbNorth].LineStyle)+1) shl 8);
|
||||
if cbSouth in ABorders then
|
||||
XFBorderDWord1 := XFBorderDWord1 or ((ord(ABorderStyles[cbSouth].LineStyle)+1) shl 12);
|
||||
if cbDiagDown in ABorders then
|
||||
XFBorderDWord1 := XFBorderDWord1 or $40000000;
|
||||
if cbDiagUp in ABorders then
|
||||
XFBorderDWord1 := XFBorderDWord1 or $80000000;
|
||||
AStream.WriteDWord(DWordToLE(XFBorderDWord1));
|
||||
|
||||
// Top and Bottom line colors
|
||||
XFBorderDWord2 := ABorderStyles[cbNorth].Color + ABorderStyles[cbSouth].Color shl 7;
|
||||
// XFBorderDWord2 := 8 {top line - black} + 8 * $80 {bottom line - black};
|
||||
// Top, bottom and diagonal line colors
|
||||
XFBorderDWord2 := ABorderStyles[cbNorth].Color + ABorderStyles[cbSouth].Color shl 7 +
|
||||
ABorderStyles[cbDiagUp].Color shl 14;
|
||||
// In BIFF8 both diagonals have the same color - we use the color of the up-diagonal.
|
||||
|
||||
// Diagonal line style
|
||||
if (ABorders + [cbDiagUp, cbDiagDown] <> []) then
|
||||
XFBorderDWord2 := XFBorderDWord2 or ((ord(ABorderStyles[cbDiagUp].LineStyle)+1) shl 21);
|
||||
// In BIFF8 both diagonals have the same color - we use the color of the up-diagonal.
|
||||
|
||||
// Add a background, if desired
|
||||
if AddBackground then XFBorderDWord2 := XFBorderDWord2 or $4000000;
|
||||
@ -1922,12 +1937,23 @@ begin
|
||||
Include(lData.Borders, cbSouth);
|
||||
lData.BorderStyles[cbSouth].LineStyle := FixLineStyle(dw shr 12);
|
||||
end;
|
||||
dw := xf.Border_Background_2 and MASK_XF_BORDER_DIAGONAL;
|
||||
if dw <> 0 then begin
|
||||
lData.BorderStyles[cbDiagUp].LineStyle := FixLineStyle(dw shr 21);
|
||||
lData.BorderStyles[cbDiagDown].LineStyle := lData.BorderStyles[cbDiagUp].LineStyle;
|
||||
if xf.Border_Background_1 and MASK_XF_BORDER_SHOW_DIAGONAL_UP <> 0 then
|
||||
Include(lData.Borders, cbDiagUp);
|
||||
if xf.Border_Background_1 and MASK_XF_BORDER_SHOW_DIAGONAL_DOWN <> 0 then
|
||||
Include(lData.Borders, cbDiagDown);
|
||||
end;
|
||||
|
||||
// Border line colors
|
||||
lData.BorderStyles[cbWest].Color := (xf.Border_Background_1 and MASK_XF_BORDER_LEFT_COLOR) shr 16;
|
||||
lData.BorderStyles[cbEast].Color := (xf.Border_Background_1 and MASK_XF_BORDER_RIGHT_COLOR) shr 23;
|
||||
lData.BorderStyles[cbNorth].Color := (xf.Border_Background_2 and MASK_XF_BORDER_TOP_COLOR);
|
||||
lData.BorderStyles[cbSouth].Color := (xf.Border_Background_2 and MASK_XF_BORDER_BOTTOM_COLOR) shr 7;
|
||||
lData.BorderStyles[cbDiagUp].Color := (xf.Border_Background_2 and MASK_XF_BORDER_DIAGONAL_COLOR) shr 14;
|
||||
lData.BorderStyles[cbDiagDown].Color := lData.BorderStyles[cbDiagUp].Color;
|
||||
|
||||
// Background fill pattern
|
||||
fill := (xf.Border_Background_2 and MASK_XF_BACKGROUND_PATTERN) shr 26;
|
||||
|
@ -599,40 +599,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
(*
|
||||
AppendToStream(AStream, Format(
|
||||
'<fills count="%d">', [Length(FFillList)]));
|
||||
|
||||
// index 0 -- built-in empty fill
|
||||
AppendToStream(AStream,
|
||||
'<fill>',
|
||||
'<patternFill patternType="none" />',
|
||||
'</fill>');
|
||||
|
||||
// index 1 -- built-in gray125 pattern
|
||||
AppendToStream(AStream,
|
||||
'<fill>',
|
||||
'<patternFill patternType="gray125" />',
|
||||
'</fill>');
|
||||
|
||||
// user-defined fills
|
||||
for i:=2 to High(FFillList) do begin
|
||||
styleCell := FFillList[i];
|
||||
rgb := Workbook.GetPaletteColor(styleCell^.BackgroundColor);
|
||||
AppendToStream(AStream,
|
||||
'<fill>',
|
||||
'<patternFill patternType="solid">');
|
||||
AppendToStream(AStream, Format(
|
||||
'<fgColor rgb="%s" />', [Copy(ColorToHTMLColorStr(rgb), 2, 255)]),
|
||||
'<bgColor indexed="64" />');
|
||||
AppendToStream(AStream,
|
||||
'</patternFill>',
|
||||
'</fill>');
|
||||
end;
|
||||
|
||||
AppendToStream(FSStyles,
|
||||
'</fills>');
|
||||
*)
|
||||
procedure TsSpreadOOXMLReader.ReadFont(ANode: TDOMNode);
|
||||
var
|
||||
node: TDOMNode;
|
||||
|
Reference in New Issue
Block a user