diff --git a/components/fpspreadsheet/examples/fpsgrid/mainform.lfm b/components/fpspreadsheet/examples/fpsgrid/mainform.lfm index f4b683368..dc1a7fd7f 100644 --- a/components/fpspreadsheet/examples/fpsgrid/mainform.lfm +++ b/components/fpspreadsheet/examples/fpsgrid/mainform.lfm @@ -63,7 +63,7 @@ object Form1: TForm1 TabOrder = 1 TitleStyle = tsNative ColWidths = ( - 56 + 42 64 64 64 @@ -104,19 +104,19 @@ object Form1: TForm1 TabOrder = 2 object Label1: TLabel Left = 8 - Height = 20 + Height = 15 Top = 9 - Width = 46 + Width = 37 Caption = 'Sheets:' ParentColor = False end object SheetsCombo: TComboBox Left = 72 - Height = 28 + Height = 23 Top = 4 Width = 808 Anchors = [akTop, akLeft, akRight] - ItemHeight = 20 + ItemHeight = 15 ItemIndex = 0 Items.Strings = ( 'Sheet 1' @@ -129,7 +129,7 @@ object Form1: TForm1 end object OpenDialog: TOpenDialog DefaultExt = '.xls' - Filter = 'Excel spreadsheet (*.xls)|*.xls|Excel XML spreadsheet (*.xlsx)|*.xlxs|LibreOffice/OpenOffice spreadsheet (*.ods)|*.ods|Wikitable (pipes) (.wikitable_pipes)|.wikitable_pipes|All files (*.*)|*.*' + Filter = 'Excel spreadsheet (*.xls)|*.xls|Excel XML spreadsheet (*.xlsx)|*.xlsx|LibreOffice/OpenOffice spreadsheet (*.ods)|*.ods|Wikitable (pipes) (.wikitable_pipes)|.wikitable_pipes|All files (*.*)|*.*' Options = [ofExtensionDifferent, ofEnableSizing, ofViewDetail] left = 184 top = 200 diff --git a/components/fpspreadsheet/examples/spready/spready.lpi b/components/fpspreadsheet/examples/spready/spready.lpi index a15f17ce2..954415697 100644 --- a/components/fpspreadsheet/examples/spready/spready.lpi +++ b/components/fpspreadsheet/examples/spready/spready.lpi @@ -87,6 +87,7 @@ + diff --git a/components/fpspreadsheet/fpspreadsheetgrid.pas b/components/fpspreadsheet/fpspreadsheetgrid.pas index 61d858f10..a3d69b4df 100644 --- a/components/fpspreadsheet/fpspreadsheetgrid.pas +++ b/components/fpspreadsheet/fpspreadsheetgrid.pas @@ -48,6 +48,7 @@ type FCellFont: TFont; FAutoCalc: Boolean; FReadFormulas: Boolean; + FDrawingCell: PCell; function CalcAutoRowHeight(ARow: Integer): Integer; function CalcColWidth(AWidth: Single): Integer; function CalcRowHeight(AHeight: Single): Integer; @@ -123,6 +124,7 @@ type procedure DrawCellBorders(ACol, ARow: Integer; ARect: TRect); overload; procedure DrawFocusRect(aCol,aRow:Integer; ARect:TRect); override; procedure DrawFrozenPaneBorders(ARect: TRect); + procedure DrawRow(aRow: Integer); override; procedure DrawSelection; procedure DrawTextInCell(ACol, ARow: Integer; ARect: TRect; AState: TGridDrawState); override; function GetCellHeight(ACol, ARow: Integer): Integer; @@ -1269,7 +1271,8 @@ end; } procedure TsCustomWorksheetGrid.DrawFrozenPaneBorders(ARect: TRect); begin - if FWorkSheet = nil then exit; + if FWorkSheet = nil then + exit; if (soHasFrozenPanes in FWorksheet.Options) then begin Canvas.Pen.Style := psSolid; Canvas.Pen.Color := clBlack; @@ -1281,6 +1284,143 @@ begin end; end; +{@@ + Draws a complete row of cells. Is mostly duplicated from Grids.pas in order + to be able to add code for merged cells and overflow text. +} +procedure TsCustomWorksheetGrid.DrawRow(ARow: Integer); +var + gds: TGridDrawState; + r, c, cNext: Integer; + Rs: Boolean; + rct, saved_rct: TRect; + clipArea: Trect; + cell: PCell; + r1,c1,r2,c2: Cardinal; + tmp: Integer; + + function IsPushCellActive: boolean; + begin + with GCache do + result := (PushedCell.X<>-1) and (PushedCell.Y<>-1); + end; + + function VerticalIntersect(const aRect,bRect: TRect): boolean; + begin + result := (aRect.Top < bRect.Bottom) and (aRect.Bottom > bRect.Top); + end; + + function HorizontalIntersect(const aRect,bRect: TRect): boolean; + begin + result := (aRect.Left < bRect.Right) and (aRect.Right > bRect.Left); + end; + + procedure DoDrawCell(_col, _row: Integer); + var + Rgn: HRGN; + begin + with GCache do begin + if (_col = HotCell.x) and (_row = HotCell.y) and not IsPushCellActive() then begin + Include(gds, gdHot); + HotCellPainted := True; + end; + if ClickCellPushed and (_col = PushedCell.x) and (_row = PushedCell.y) then begin + Include(gds, gdPushed); + end; + end; + + Canvas.SaveHandleState; + try + Rgn := CreateRectRgn(rct.Left, rct.Top, rct.Right, rct.Bottom); + SelectClipRgn(Canvas.Handle, Rgn); + DrawCell(_col, _row, rct, gds); + DeleteObject(Rgn); + finally + Canvas.RestoreHandleState; + end; + end; + +begin + // Upper and Lower bounds for this row + ColRowToOffSet(False, True, ARow, rct.Top, rct.Bottom); + saved_rct := rct; + + // is this row within the ClipRect? + clipArea := Canvas.ClipRect; + if (rct.Top >= rct.Bottom) or not VerticalIntersect(rct, clipArea) then begin + {$IFDEF DbgVisualChange} + DebugLn('Drawrow: Skipped row: ', IntToStr(aRow)); + {$ENDIF} + exit; + end; + + // Draw columns in this row + with GCache.VisibleGrid do begin + c := Left; + while c <= Right do begin + r := ARow; + rct := saved_rct; + // FDrawingCell is the cell which is currently being painted. We store + // it to avoid excessive calls to "FindCell". + FDrawingCell := nil; + cNext := c + 1; + if (FWorksheet <> nil) and (r >= FixedRows) and (c >= FixedCols) then + begin + cell := FWorksheet.FindCell(GetWorksheetRow(r), GetWorksheetCol(c)); + if (cell = nil) or (cell^.MergedNeighbors = []) then + // single cell + FDrawingCell := cell + else + begin + // merged cells + FDrawingCell := FWorksheet.FindMergeBase(cell); + FWorksheet.FindMergedRange(FDrawingCell, r1, c1, r2, c2); + r := GetGridRow(r1); + ColRowToOffSet(False, True, r, rct.Top, tmp); + ColRowToOffSet(False, True, r + r2 - r1, tmp, rct.Bottom); + cNext := c + (c2-c1) + 1; + end; + end; + + ColRowToOffset(true, true, c, rct.Left, tmp); + ColRowToOffset(true, true, cNext-1, tmp, rct.Right); + + if (rct.Left >= rct.Right) or not HorizontalIntersect(rct, clipArea) then + continue; + Rs := (goRowSelect in Options); + gds := GetGridDrawState(c, r); + DoDrawCell(c, r); + + c := cNext; + end; + + // Draw the focus Rect + if FocusRectVisible and (ARow = Row) and + ((Rs and (ARow >= Top) and (ARow <= Bottom)) or IsCellVisible(Col, ARow)) + then begin + if EditorMode then begin + //if EditorAlwaysShown and (FEditor<>nil) and FEditor.Visible then begin + //DebugLn('No Draw Focus Rect'); + end else begin + ColRowToOffset(true, true, Col, rct.Left, rct.Right); + // is this column within the ClipRect? + if HorizontalIntersect(rct, clipArea) then + DrawFocusRect(Col, Row, rct); + end; + end; + end; + + // Draw Fixed Columns + r := ARow; + for c := 0 to FixedCols-1 do begin + gds := [gdFixed]; + ColRowToOffset(True, True, c, rct.Left, rct.Right); + // is this column within the ClipRect? + if (rct.Left < rct.Right) and HorizontalIntersect(rct, clipArea) then + DoDrawCell(c, r); + end; +end; + {@@ Draws the selection rectangle around selected cells, 3 pixels wide as in Excel. } @@ -1336,13 +1476,15 @@ begin if (FWorksheet = nil) then exit; + lCell := FDrawingCell; + { c := ACol - FHeaderCount; r := ARow - FHeaderCount; if (r >= 0) and (c >= 0) then lCell := FWorksheet.FindCell(r, c) else lCell := nil; - + } // Header if lCell = nil then begin if ShowHeaders and ((ACol = 0) or (ARow = 0)) then begin @@ -2004,11 +2146,14 @@ begin end; if FWorksheet <> nil then begin + lCell := FDrawingCell; + { r := ARow - FHeaderCount; c := ACol - FHeaderCount; lCell := FWorksheet.FindCell(r, c); + } if lCell <> nil then begin - Result := FWorksheet.ReadAsUTF8Text(r, c); + Result := FWorksheet.ReadAsUTF8Text(lCell); if lCell^.TextRotation = rtStacked then begin s := Result; Result := '';