diff --git a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr index 0f950117c..716730d87 100644 --- a/components/fpspreadsheet/examples/excel5demo/excel5write.lpr +++ b/components/fpspreadsheet/examples/excel5demo/excel5write.lpr @@ -33,7 +33,7 @@ begin // Create the spreadsheet MyWorkbook := TsWorkbook.Create; - MyWorksheet := MyWorkbook.AddWorksheet(Str_Worksheet1); + MyWorksheet := MyWorkbook.AddWorksheet(UTF8ToAnsi(Str_Worksheet1)); MyWorksheet.Options := MyWorksheet.Options + [soHasFrozenPanes]; MyWorksheet.LeftPaneWidth := 1; diff --git a/components/fpspreadsheet/examples/excel8demo/excel8write.lpr b/components/fpspreadsheet/examples/excel8demo/excel8write.lpr index 248df45ec..95276f26b 100644 --- a/components/fpspreadsheet/examples/excel8demo/excel8write.lpr +++ b/components/fpspreadsheet/examples/excel8demo/excel8write.lpr @@ -56,9 +56,10 @@ begin MyWorksheet.LeftPaneWidth := 20*72*2; // 72 pt = inch --> 2 inches = 5 cm } // Write some cells - MyWorksheet.WriteNumber(0, 1, 2.0);// B1 - MyWorksheet.WriteNumber(0, 2, 3.0);// C1 - MyWorksheet.WriteNumber(0, 3, 4.0);// D1 + MyWorksheet.WriteNumber(0, 0, 1.0); // A1 + MyWorksheet.WriteNumber(0, 1, 2.0); // B1 + MyWorksheet.WriteNumber(0, 2, 3.0); // C1 + MyWorksheet.WriteNumber(0, 3, 4.0); // D1 MyWorksheet.WriteUTF8Text(4, 2, Str_Total);// C5 MyWorksheet.WriteNumber(4, 3, 10); // D5 diff --git a/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi b/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi index 3be3feee6..ed788ad24 100644 --- a/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi +++ b/components/fpspreadsheet/examples/fpsgrid/fpsgrid.lpi @@ -48,6 +48,9 @@ + + + @@ -79,6 +82,9 @@ + + + @@ -137,6 +143,9 @@ + + + diff --git a/components/fpspreadsheet/examples/spready/mainform.lfm b/components/fpspreadsheet/examples/spready/mainform.lfm index 12c90740b..d24057e00 100644 --- a/components/fpspreadsheet/examples/spready/mainform.lfm +++ b/components/fpspreadsheet/examples/spready/mainform.lfm @@ -967,10 +967,6 @@ object Form1: TForm1 } end end - object MnuWordwrap: TMenuItem - Action = AcWordwrap - AutoCheck = True - end object MnuNumberFormat: TMenuItem Caption = 'Number format' object MenuItem33: TMenuItem @@ -1014,6 +1010,9 @@ object Form1: TForm1 Action = AcNFShortDateTime AutoCheck = True end + object MenuItem60: TMenuItem + Caption = '-' + end object MenuItem52: TMenuItem Action = AcNFShortDate AutoCheck = True @@ -1030,6 +1029,9 @@ object Form1: TForm1 Action = AcNFCustomMY AutoCheck = True end + object MenuItem61: TMenuItem + Caption = '-' + end object MenuItem56: TMenuItem Action = AcNFShortTime AutoCheck = True @@ -1046,6 +1048,17 @@ object Form1: TForm1 Action = AcNFLongTimeAM AutoCheck = True end + object MenuItem62: TMenuItem + Caption = '-' + end + object MenuItem63: TMenuItem + Action = AcNFTimeInterval + AutoCheck = True + end + end + object MnuWordwrap: TMenuItem + Action = AcWordwrap + AutoCheck = True end end end diff --git a/components/fpspreadsheet/examples/spready/mainform.pas b/components/fpspreadsheet/examples/spready/mainform.pas index 68810ce75..885e2d36a 100644 --- a/components/fpspreadsheet/examples/spready/mainform.pas +++ b/components/fpspreadsheet/examples/spready/mainform.pas @@ -142,6 +142,10 @@ type MenuItem57: TMenuItem; MenuItem58: TMenuItem; MenuItem59: TMenuItem; + MenuItem60: TMenuItem; + MenuItem61: TMenuItem; + MenuItem62: TMenuItem; + MenuItem63: TMenuItem; MnuFmtDateTimeMSZ: TMenuItem; MnuTimeInterval: TMenuItem; MnuShortTimeAM: TMenuItem; @@ -281,6 +285,8 @@ uses fpcanvas, fpsutils, fpsnumformatparser; const + DROPDOWN_COUNT = 24; + HORALIGN_TAG = 100; VERTALIGN_TAG = 110; TEXTROT_TAG = 130; @@ -305,6 +311,7 @@ const TB_INNER_BORDER = $0800; // Use a combination of these bits for the "Tag" of the Border actions - see FormCreate. + { TForm1 } procedure TForm1.AcEditExecute(Sender: TObject); @@ -695,6 +702,8 @@ begin FormatToolbar.Height := FontCombobox.Height + 2*FontCombobox.Top; FormatToolbar.ButtonHeight := FormatToolbar.Height - 4; + CbBackgroundCOlor.Height := FontCombobox.Height; + // Populate font combobox FontCombobox.Items.Assign(Screen.Fonts); @@ -714,6 +723,10 @@ begin AcBorderOuter.Tag := LEFT_BORDER_THIN + RIGHT_BORDER_THIN + TOP_BORDER_THIN + BOTTOM_BORDER_THIN; AcBorderOuterMedium.Tag := LEFT_BORDER_THICK + RIGHT_BORDER_THICK + TOP_BORDER_THICK + BOTTOM_BORDER_THICK; AcBorderAll.Tag := AcBorderOuter.Tag + AcBorderInner.Tag; + + FontCombobox.DropDownCount := DROPDOWN_COUNT; + FontSizeCombobox.DropDownCount := DROPDOWN_COUNT; + CbBackgroundColor.DropDownCount := DROPDOWN_COUNT; end; procedure TForm1.LoadFile(const AFileName: String); diff --git a/components/fpspreadsheet/examples/spready/spready.lpi b/components/fpspreadsheet/examples/spready/spready.lpi index 431986deb..e116128ee 100644 --- a/components/fpspreadsheet/examples/spready/spready.lpi +++ b/components/fpspreadsheet/examples/spready/spready.lpi @@ -47,6 +47,9 @@ + + + @@ -78,6 +81,9 @@ + + + @@ -136,6 +142,9 @@ + + + diff --git a/components/fpspreadsheet/fpspreadsheet.pas b/components/fpspreadsheet/fpspreadsheet.pas index 4cea0f812..a4c6a2c8a 100755 --- a/components/fpspreadsheet/fpspreadsheet.pas +++ b/components/fpspreadsheet/fpspreadsheet.pas @@ -301,6 +301,7 @@ const // Will be removed sooner or later... scRGBColor = $FFFF; + scTransparent = $FFFE; scNotDefined = $FFFF; type @@ -472,7 +473,7 @@ type FOnChangeCell: TsCellEvent; FOnChangeFont: TsCellEvent; function GetFormatSettings: TFormatSettings; - procedure RemoveCallback(data, arg: pointer); + procedure RemoveCallback(data, arg: pointer); protected procedure ChangedCell(ARow, ACol: Cardinal); @@ -2307,12 +2308,33 @@ begin ChangedCell(ARow, ACol); end; +{@@ + Writes data defined as a string into a cell. Depending on the structure of the + string, the worksheet tries to guess whether it is a number, a date/time or + a text and calls the corresponding writing method. + + @param ARow Row index of the cell + @param ACol Column index of the cell + @param AValue Value to be written into the cell given as a string. Depending + on the structure of the string, however, the value is written + as a number, a date/time or a text. +} procedure TsWorksheet.WriteCellValueAsString(ARow, ACol: Cardinal; AValue: String); begin WriteCellValueAsString(GetCell(ARow, ACol), AValue); end; +{@@ + Writes data defined as a string into a cell. Depending on the structure of the + string, the worksheet tries to guess whether it is a number, a date/time or + a text and calls the corresponding writing method. + + @param ACell Poiner to the cell + @param AValue Value to be written into the cell given as a string. Depending + on the structure of the string, however, the value is written + as a number, a date/time or a text. +} procedure TsWorksheet.WriteCellValueAsString(ACell: PCell; AValue: String); var isPercent: Boolean; @@ -2716,12 +2738,18 @@ procedure TsWorksheet.WriteNumberFormat(ACell: PCell; begin if ACell = nil then exit; - Include(ACell^.UsedFormattingFields, uffNumberFormat); + ACell^.NumberFormat := ANumberFormat; - if (AFormatString = '') then - ACell^.NumberFormatStr := BuildNumberFormatString(ANumberFormat, Workbook.FormatSettings) - else - ACell^.NumberFormatStr := AFormatString; + if ANumberFormat <> nfGeneral then begin + Include(ACell^.UsedFormattingFields, uffNumberFormat); + if (AFormatString = '') then + ACell^.NumberFormatStr := BuildNumberFormatString(ANumberFormat, Workbook.FormatSettings) + else + ACell^.NumberFormatStr := AFormatString; + end else begin + Exclude(ACell^.UsedFormattingFields, uffNumberFormat); + ACell^.NumberFormatStr := ''; + end; ChangedCell(ACell^.Row, ACell^.Col); end; @@ -2932,7 +2960,8 @@ end; @param ARow Row index of the cell @param ACol Column index of the cell @param AColor Index of the new background color into the workbook's - color palette. + color palette. Use the color index scTransparent to + erase an existing background color. } procedure TsWorksheet.WriteBackgroundColor(ARow, ACol: Cardinal; AColor: TsColor); @@ -2940,8 +2969,12 @@ var ACell: PCell; begin ACell := GetCell(ARow, ACol); - ACell^.UsedFormattingFields := ACell^.UsedFormattingFields + [uffBackgroundColor]; - ACell^.BackgroundColor := AColor; + if AColor = scTransparent then + Exclude(ACell^.UsedFormattingFields, uffBackgroundColor) + else begin + Include(ACell^.UsedFormattingFields, uffBackgroundColor); + ACell^.BackgroundColor := AColor; + end; ChangedCell(ARow, ACol); end; @@ -3086,7 +3119,7 @@ var lCell: PCell; begin lCell := GetCell(ARow, ACol); - lCell^.UsedFormattingFields := lCell^.UsedFormattingFields + [uffHorAlign]; + Include(lCell^.UsedFormattingFields, uffHorAlign); lCell^.HorAlignment := AValue; ChangedCell(ARow, ACol); end; @@ -3104,7 +3137,7 @@ var lCell: PCell; begin lCell := GetCell(ARow, ACol); - lCell^.UsedFormattingFields := lCell^.UsedFormattingFields + [uffVertAlign]; + Include(lCell^.UsedFormattingFields, uffVertAlign); lCell^.VertAlignment := AValue; ChangedCell(ARow, ACol); end; diff --git a/components/fpspreadsheet/fpspreadsheetgrid.pas b/components/fpspreadsheet/fpspreadsheetgrid.pas index 3b675d6ba..756d1a2ae 100644 --- a/components/fpspreadsheet/fpspreadsheetgrid.pas +++ b/components/fpspreadsheet/fpspreadsheetgrid.pas @@ -113,6 +113,7 @@ type procedure DrawCellBorders; overload; procedure DrawCellBorders(ACol, ARow: Integer; ARect: TRect); overload; procedure DrawFocusRect(aCol,aRow:Integer; ARect:TRect); override; + procedure DrawFrozenPaneBorders(ARect: TRect); procedure DrawSelection; procedure DrawTextInCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); override; function GetBorderStyle(ACol, ARow, ADeltaCol, ADeltaRow: Integer; @@ -478,6 +479,11 @@ end; { TsCustomWorksheetGrid } +{@@ + Constructor of the grid. Activates the display of column and row headers + and creates an internal "CellFont". Creates a given number of empty rows + and columns. +} constructor TsCustomWorksheetGrid.Create(AOwner: TComponent); begin inherited Create(AOwner); @@ -487,6 +493,9 @@ begin FCellFont := TFont.Create; end; +{@@ + Destructor of the grid: Destroys the workbook and the internal CellFont +} destructor TsCustomWorksheetGrid.Destroy; begin FreeAndNil(FWorkbook); @@ -494,15 +503,24 @@ begin inherited Destroy; end; -{ Suppresses unnecessary repaints. } +{@@ + The BeginUpdate/EndUpdate pair suppresses unnecessary painting of the grid. + Call BeginUpdate to stop refreshing the grid, and call EndUpdate to release + the lock and to repaint the grid again. +} procedure TsCustomWorksheetGrid.BeginUpdate; begin inc(FLockCount); end; -{ Converts the column width, given in "characters" of the default font, to pixels - All chars are assumed to have the same width defined by the "0". - Therefore, this calculation is only approximate. } +{@@ + Converts the column width, given in "characters" of the default font, to pixels + All chars are assumed to have the same width defined by the width of the + "0" character. Therefore, this calculation is only approximate. + + @param AWidth Width of a column given as "character count". + @return Column width in pixels. +} function TsCustomWorksheetGrid.CalcColWidth(AWidth: Single): Integer; var w0: Integer; @@ -512,9 +530,14 @@ begin Result := Round(AWidth * w0); end; -{ Finds the max cell height per row and uses this to define the RowHeights[]. - Returns DefaultRowHeight if the row does not contain any cells. - ARow is a grid row index. } +{@@ + Finds the maximum cell height per row and uses this to define the RowHeights[]. + Returns DefaultRowHeight if the row does not contain any cells, or if the + worksheet does not have a TRow record for this particular row. + ARow is a grid row index. + + @param ARow Index of the row, in grid units +} function TsCustomWorksheetGrid.CalcAutoRowHeight(ARow: Integer): Integer; var c: Integer; @@ -529,7 +552,14 @@ begin Result := h; end; -{ Converts the row height (from a worksheet row), given in lines, to pixels } +{@@ + Converts the row height (from a worksheet row record), given in lines, to + pixels as needed by the grid + + @param AHeight Row height expressed as default font line count from the + worksheet + @result Row height in pixels +} function TsCustomWorksheetGrid.CalcRowHeight(AHeight: Single): Integer; var h_pts: Single; @@ -538,15 +568,32 @@ begin Result := PtsToPX(h_pts, Screen.PixelsPerInch) + 4; end; +{@@ + Handler for the event OnChangeCell fired by the worksheet when the contents + of formatting of a cell has changed. + As a consequence, the grid may have to update the cell. + Row/Col coordinates are in worksheet units here! + + @param ASender Sender of the event OnChangeFont (the worksheet) + @param ARow Row index of the changed cell, in worksheet units! + @param ACol Column index of the changed cell, in worksheet units! +} procedure TsCustomWorksheetGrid.ChangedCellHandler(ASender: TObject; ARow, ACol:Cardinal); begin Unused(ASender, ARow, ACol); if FLockCount = 0 then Invalidate; end; -{ Handler for the event that the font has changed in a given cell. - As a consequence, the row height may have to be adapted. - Row/Col coordinates are in worksheet units here! } +{@@ + Handler for the event OnChangeFont fired by the worksheet when the font has + changed in a cell. + As a consequence, the grid may have to update the row height. + Row/Col coordinates are in worksheet units here! + + @param ASender Sender of the event OnChangeFont (the worksheet) + @param ARow Row index of the cell with the changed font, in worksheet units! + @param ACol Column index of the cell with the changed font, in worksheet units! +} procedure TsCustomWorksheetGrid.ChangedFontHandler(ASender: TObject; ARow, ACol: Cardinal); var lRow: PRow; @@ -564,7 +611,12 @@ begin end; end; -{ Converts a spreadsheet font to a font used for painting (TCanvas.Font). } +{@@ + Converts a spreadsheet font to a font used for painting (TCanvas.Font). + + @param sFont Font as used by fpspreadsheet (input) + @param AFont Font as used by TCanvas for painting (output) +} procedure TsCustomWorksheetGrid.Convert_sFont_to_Font(sFont: TsFont; AFont: TFont); begin if Assigned(AFont) and Assigned(sFont) then begin @@ -579,7 +631,12 @@ begin end; end; -{ Converts a font used for painting (TCanvas.Font) to a spreadsheet font } +{@@ + Converts a font used for painting (TCanvas.Font) to a spreadsheet font + + @param AFont Font as used by TCanvas for painting (input) + @param sFont Font as used by fpspreadsheet (output) +} procedure TsCustomWorksheetGrid.Convert_Font_to_sFont(AFont: TFont; sFont: TsFont); begin if Assigned(AFont) and Assigned(sFont) then begin @@ -594,8 +651,20 @@ begin end; end; -{ Is overridden to show "frozen" cells in the same style as normal cells. - "Frozen" cells are internally "fixed" cells of the grid. } +{@@ + This is one of the main painting methods inherited from TsCustomGrid. It is + overridden here to achieve the feature of "frozen" cells which should be + painted in the same style as normal cells. + + Internally, "frozen" cells are "fixed" cells of the grid. Therefore, it is + not possible to select any cell within the frozen panes - in contrast to the + standard spreadsheet applications. + + @param ACol Column index of the cell being drawn + @param ARow Row index of the cell beging drawn + @param ARect Rectangle, in grid pixels, covered by the cell + @param AState Grid drawing state, as defined by TsCustomGrid +} procedure TsCustomWorksheetGrid.DefaultDrawCell(aCol, aRow: Integer; var aRect: TRect; AState: TGridDrawState); var @@ -614,7 +683,6 @@ begin end; if wasFixed then begin - wasFixed := true; // ????? AState := AState - [gdFixed]; Canvas.Brush.Color := clWindow; end; @@ -627,8 +695,14 @@ begin end; end; -{ Adjusts the grid's canvas before painting a given cell. Considers, e.g. - background color, horizontal alignment, vertical alignment, etc. } +{@@ + Adjusts the grid's canvas before painting a given cell. Considers, e.g. + background color, horizontal alignment, vertical alignment, etc. + + @param ACol Column index of the cell being painted + @param ARow Row index of the cell being painted + @param AState Grid drawing state -- see TsCustomGrid. +} procedure TsCustomWorksheetGrid.DoPrepareCanvas(ACol, ARow: Integer; AState: TGridDrawState); var @@ -711,10 +785,13 @@ begin inherited DoPrepareCanvas(ACol, ARow, AState); end; -{ Is overridden in order to paint the cell borders and the selection rectangle. - Both features can extend into the neighbor cells and thus are clipped at the - cell borders by the standard painting mechanism. In DrawAllRows, clipping at - cell borders is no longer active. } +{@@ + This method is inherited from TsCustomGrid, but is overridden here in order + to paint the cell borders and the selection rectangle. + Both features can extend into the neighbor cells and thus would be clipped + at the cell borders by the standard painting mechanism. At the time when + DrawAllRows is called, however, clipping at cell borders is no longer active. +} procedure TsCustomWorksheetGrid.DrawAllRows; var cliprect: TRect; @@ -731,6 +808,9 @@ begin ColRowToOffset(True, True, FixedCols-1, tmp, cliprect.Left); if FixedRows > 0 then ColRowToOffset(False, True, FixedRows-1, tmp, cliprect.Top); + + DrawFrozenPaneBorders(clipRect); + rgn := CreateRectRgn(cliprect.Left, cliprect.top, cliprect.Right, cliprect.Bottom); SelectClipRgn(Canvas.Handle, Rgn); @@ -743,7 +823,9 @@ begin end; end; -{ Draws the borders of all cells. } +{@@ + Draws the borders of all cells. Calls DrawCellBorder for each individual cell. +} procedure TsCustomWorksheetGrid.DrawCellBorders; var cell: PCell; @@ -764,10 +846,16 @@ begin end; end; -{ Draws the border lines around a given cell. Note that when this procedure is +{@@ + Draws the border lines around a given cell. Note that when this procedure is called the output is clipped by the cell rectangle, but thick and double border styles extend into the neighbor cell. Therefore, these border lines - are drawn in parts. } + are drawn in parts. + + @param ACol Column Index + @param ARow Row index + @param ARect Rectangle in pixels occupied by the cell. +} procedure TsCustomWorksheetGrid.DrawCellBorders(ACol, ARow: Integer; ARect: TRect); procedure DrawBorderLine(ACoord: Integer; ARect: TRect; IsHor: Boolean; @@ -858,7 +946,29 @@ begin // Nothing do to end; -{ Draws the selection rectangle, 3 pixels wide as in Excel. } +{@@ + Draws a solid line along the borders of frozen panes. + + @param ARect This rectangle indicates the area with movable cells. If the + grid has frozen panes a black line is drawn along the upper + and/or left edge of this rectangle. +} +procedure TsCustomWorksheetGrid.DrawFrozenPaneBorders(ARect: TRect); +begin + if (soHasFrozenPanes in FWorksheet.Options) then begin + Canvas.Pen.Style := psSolid; + Canvas.Pen.Color := clBlack; + Canvas.Pen.Width := 1; + if FFrozenRows > 0 then + Canvas.Line(ARect.Left, ARect.Top, ARect.Right, ARect.Top); + if FFrozenCols > 0 then + Canvas.Line(ARect.Left, ARect.Top, ARect.Left, ARect.Bottom); + end; +end; + +{@@ + Draws the selection rectangle, 3 pixels wide as in Excel. +} procedure TsCustomWorksheetGrid.DrawSelection; var P1, P2: TPoint; @@ -884,9 +994,16 @@ begin Canvas.Rectangle(P1.X, P1.Y, P2.X, P2.Y); end; -{ Draws the cell text. Calls "GetCellText" to determine the text in the cell. +{@@ + Draws the cell text. Calls "GetCellText" to determine the text in the cell. Takes care of horizontal and vertical text alignment, text rotation and - text wrapping } + text wrapping + + @param ACol Column index of the cell + @param ARow Row index of the cell + @param ARect Rectangle in pixels occupied by the cell. + @param AState Drawing state of the grid -- see TCustomGrid +} procedure TsCustomWorksheetGrid.DrawTextInCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); var @@ -970,6 +1087,12 @@ begin txtRot, wrapped, false); end; +{@@ + Is called when editing of a cell is completed. Determines the worksheet cell + and writes the text into the worksheet. Tries to keep the format of the cell, + but if it is a new cell, or the content type has changed, tries to figure out + the content type (number, date/time, text). +} procedure TsCustomWorksheetGrid.EditingDone; var oldText: String; @@ -989,14 +1112,24 @@ begin FEditing := false; end; +{@@ + The BeginUpdate/EndUpdate pair suppresses unnecessary painting of the grid. + Call BeginUpdate to stop refreshing the grid, and call EndUpdate to release + the lock and to repaint the grid again. +} procedure TsCustomWorksheetGrid.EndUpdate; begin dec(FLockCount); if FLockCount = 0 then Invalidate; end; -{ Copies the borders of a cell to its neighbors. This avoids the nightmare of - changing borders due to border conflicts of adjacent cells. } +{@@ + Copies the borders of a cell to its neighbors. This avoids the nightmare of + changing borders due to border conflicts of adjacent cells. + + @param ACol Column index of the cell + @param ARow Row index of the cell +} procedure TsCustomWorksheetGrid.FixNeighborCellBorders(ACol, ARow: Integer); procedure SetNeighborBorder(NewRow, NewCol: Integer; @@ -1032,10 +1165,14 @@ begin end; end; -{ The "colors" used by the spreadsheet are indexes into the workbook's color +{@@ + The "colors" used by the spreadsheet are indexes into the workbook's color palette. If the user wants to set a color to a particular rgb value this is not possible in general. The method FindNearestPaletteIndex finds the bast - matching color in the palette. } + matching color in the palette. + + @param AColor Color index into the workbook's palette +} function TsCustomWorksheetGrid.FindNearestPaletteIndex(AColor: TColor): TsColor; procedure ColorToHSL(RGB: TColor; out H, S, L : double); @@ -1121,6 +1258,14 @@ begin end; end; +{@@ + Returns the background color of a cell. The color is given as an index into + the workbook's color palette. + + @param ACol Column index of the cell + @param ARow Row index of the cell + @result Color index of the cell's background color. +} function TsCustomWorksheetGrid.GetBackgroundColor(ACol, ARow: Integer): TsColor; var cell: PCell; @@ -1133,6 +1278,17 @@ begin end; end; +{@@ + Returns the background color of a cell range defined by a rectangle. The color + is given as an index into the workbook's color palette. If the colors are + different from cell to cell the value scUndefined is returned. + + @param ARect Cell range defined as a rectangle: Left/Top refers to the cell + in the left/top corner of the selection, Right/Bottom to the + right/bottom corner. + @return Color index common to all cells within the selection. If the cells' + background colors are different the value scUndefined is returned. +} function TsCustomWorksheetGrid.GetBackgroundColors(ARect: TGridRect): TsColor; var c, r: Integer; @@ -1150,6 +1306,13 @@ begin end; end; +{@@ + Returns the cell borders which are drawn around a given cell. + + @param ACol Column index of the cell + @param ARow Row index of the cell + @return Set with flags indicating where borders are drawn (top/left/right/bottom) +} function TsCustomWorksheetGrid.GetCellBorder(ACol, ARow: Integer): TsCellBorders; var cell: PCell; @@ -1162,6 +1325,14 @@ begin end; end; +{@@ + Returns the cell borders which are drawn around a given rectangular cell range. + + @param ARect Rectangle defining the range of cell. + @return Set with flags indicating where borders are drawn (top/left/right/bottom) + If the individual cells within the range have different borders an + empty set is returned. +} function TsCustomWorksheetGrid.GetCellBorders(ARect: TGridRect): TsCellBorders; var c, r: Integer; diff --git a/components/fpspreadsheet/xlsbiff2.pas b/components/fpspreadsheet/xlsbiff2.pas index 1990e5c26..5052664bb 100755 --- a/components/fpspreadsheet/xlsbiff2.pas +++ b/components/fpspreadsheet/xlsbiff2.pas @@ -803,9 +803,9 @@ begin // Background color not supported, only shaded background if xf.HorAlign_Border_Background and $80 <> 0 then - lData.BackgroundColor := 1 // shaded background = "true" + lData.BackgroundColor := 1 // encodes "shaded background = true" else - ldata.BackgroundColor := 0; // shaded background = "false" + ldata.BackgroundColor := 0; // encodes "shaded background = false" // Add the decoded data to the list FXFList.Add(lData); diff --git a/components/fpspreadsheet/xlsbiff5.pas b/components/fpspreadsheet/xlsbiff5.pas index 94ed26cc8..9cf17347f 100755 --- a/components/fpspreadsheet/xlsbiff5.pas +++ b/components/fpspreadsheet/xlsbiff5.pas @@ -382,7 +382,8 @@ begin begin len := Length(Boundsheets); SetLength(Boundsheets, len + 1); - Boundsheets[len] := WriteBoundsheet(AStream, Workbook.GetWorksheetByIndex(i).Name); + Boundsheets[len] := WriteBoundsheet(AStream, UTF8ToAnsi(Workbook.GetWorksheetByIndex(i).Name)); + // BIFF8 does not support unicode --> Need UTF8ToAnsi ! end; WriteEOF(AStream); @@ -1419,6 +1420,7 @@ var xf: TXFRecord; b: Byte; dw: DWord; + fill: Word; begin AStream.ReadBuffer(xf, SizeOf(xf)); @@ -1489,8 +1491,14 @@ begin lData.BorderStyles[cbNorth].Color := (xf.Border_Background_2 and MASK_XF_BORDER_TOP_COLOR) shr 9; lData.BorderStyles[cbSouth].Color := (xf.Border_Background_1 and MASK_XF_BORDER_BOTTOM_COLOR) shr 25; + // Background fill style + fill := (xf.Border_Background_1 and MASK_XF_BKGR_FILLPATTERN) shr 16; + // Background color - lData.BackgroundColor := xf.Border_Background_1 AND MASK_XF_BKGR_PATTERN_COLOR; + if fill = 0 then + lData.BackgroundColor := scTransparent + else + lData.BackgroundColor := xf.Border_Background_1 and MASK_XF_BKGR_PATTERN_COLOR; // Add the XF to the list FXFList.Add(lData); diff --git a/components/fpspreadsheet/xlsbiff8.pas b/components/fpspreadsheet/xlsbiff8.pas index 17a48fa77..f1ad4d31c 100755 --- a/components/fpspreadsheet/xlsbiff8.pas +++ b/components/fpspreadsheet/xlsbiff8.pas @@ -266,6 +266,9 @@ const MASK_XF_BORDER_TOP_COLOR = $0000007F; MASK_XF_BORDER_BOTTOM_COLOR = $00003F80; + { XF CELL BACKGROUND PATTERN } + MASK_XF_BACKGROUND_PATTERN = $FC000000; + TEXT_ROTATIONS: Array[TsTextRotation] of Byte = ( XF_ROTATION_HORIZONTAL, XF_ROTATION_90DEG_CW, @@ -1833,6 +1836,7 @@ var xf: TXFRecord; b: Byte; dw: DWord; + fill: Integer; begin AStream.ReadBuffer(xf, SizeOf(xf)); @@ -1902,9 +1906,15 @@ begin 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; - // Background color; + // Background fill pattern + fill := (xf.Border_Background_2 and MASK_XF_BACKGROUND_PATTERN) shr 26; + + // Background color xf.Border_Background_3 := DWordLEToN(xf.Border_Background_3); - lData.BackgroundColor := xf.Border_Background_3 AND $007F; + if fill <> 0 then + lData.BackgroundColor := xf.Border_Background_3 and $007F + else + lData.BackgroundColor := scTransparent; // this means "no fill" // Add the XF to the list FXFList.Add(lData); diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index 46b3a9efb..f1a96195e 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -840,10 +840,11 @@ begin Exclude(lCell^.UsedFormattingFields, uffBorder); // Background color - if XFData.BackgroundColor <> 0 then begin + if XFData.BackgroundColor <> scTransparent then begin Include(lCell^.UsedFormattingFields, uffBackgroundColor); lCell^.BackgroundColor := XFData.BackgroundColor; - end; + end else + Exclude(lCell^.UsedFormattingFields, uffBackgroundColor); end; end;