git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.DevExpressVCL@38 05c56307-c608-d34a-929d-697000501d7a
5357 lines
164 KiB
ObjectPascal
5357 lines
164 KiB
ObjectPascal
{*******************************************************************}
|
|
{ }
|
|
{ Developer Express Cross platform Visual Component Library }
|
|
{ ExpressSpreadSheet main unit }
|
|
{ }
|
|
{ Copyright (c) 2001-2009 Developer Express Inc. }
|
|
{ ALL RIGHTS RESERVED }
|
|
{ }
|
|
{ The entire contents of this file is protected by U.S. and }
|
|
{ International Copyright Laws. Unauthorized reproduction, }
|
|
{ reverse-engineering, and distribution of all or any portion of }
|
|
{ the code contained in this file is strictly prohibited and may }
|
|
{ result in severe civil and criminal penalties and will be }
|
|
{ prosecuted to the maximum extent possible under the law. }
|
|
{ }
|
|
{ RESTRICTIONS }
|
|
{ }
|
|
{ THIS SOURCE CODE AND ALL RESULTING INTERMEDIATE FILES }
|
|
{ (DCU, OBJ, DLL, ETC.) ARE CONFIDENTIAL AND PROPRIETARY TRADE }
|
|
{ SECRETS OF DEVELOPER EXPRESS INC. THE REGISTERED DEVELOPER IS }
|
|
{ LICENSED TO DISTRIBUTE THE EXPRESSSPREADSHEET AND ALL }
|
|
{ ACCOMPANYING VCL AND CLX CONTROLS AS PART OF AN EXECUTABLE }
|
|
{ PROGRAM ONLY. }
|
|
{ }
|
|
{ THE SOURCE CODE CONTAINED WITHIN THIS FILE AND ALL RELATED }
|
|
{ FILES OR ANY PORTION OF ITS CONTENTS SHALL AT NO TIME BE }
|
|
{ COPIED, TRANSFERRED, SOLD, DISTRIBUTED, OR OTHERWISE MADE }
|
|
{ AVAILABLE TO OTHER INDIVIDUALS WITHOUT EXPRESS WRITTEN CONSENT }
|
|
{ AND PERMISSION FROM DEVELOPER EXPRESS INC. }
|
|
{ }
|
|
{ CONSULT THE END USER LICENSE AGREEMENT FOR INFORMATION ON }
|
|
{ ADDITIONAL RESTRICTIONS. }
|
|
{ }
|
|
{*******************************************************************}
|
|
|
|
unit cxSSheet;
|
|
|
|
{$I cxVer.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Math, Windows, Messages, Variants,
|
|
Forms, StdCtrls, Menus, Controls, Dialogs, Graphics, ExtCtrls,
|
|
dxCore, cxClasses, cxControls, cxGraphics,
|
|
{$IFNDEF cxLib10}
|
|
cxLookAndFeels,
|
|
{$ENDIF}
|
|
cxExcelConst, cxExcelAccess, cxSSHeaders, cxSSData,
|
|
cxSSTypes, cxSSStyles, cxSSFormulas, cxSSViewInfo, cxSSPainters, cxSSEditors,
|
|
cxSSUtils, cxSSPainterWrapper, cxSSIntf, cxSSRes, cxSSHistory, Clipbrd;
|
|
|
|
type
|
|
TcxCustomSpreadSheetBook = class;
|
|
TcxSSBookSheet = class;
|
|
ESpreadSheetError = class(EdxException);
|
|
|
|
TcxSSListenerClass = class of TcxSSListener;
|
|
TcxSSBookSheetClass = class of TcxSSBookSheet;
|
|
TcxSSFormatDialogClass = class of TcxSSFormatDialog;
|
|
|
|
TcxScrollBars = (sbsNone, sbsHorizontal, sbsVertical, sbsBoth);
|
|
|
|
{ TcxSSListener }
|
|
TcxSSListener = class
|
|
private
|
|
FLockCount: Integer;
|
|
FOwner: TcxCustomSpreadSheetBook;
|
|
protected
|
|
function BeginUpdate: Integer;
|
|
function EndUpdate: Integer;
|
|
function IsLocked: Boolean;
|
|
procedure OnActiveCellChanging(Sender: TcxSSBookSheet;
|
|
const ActiveCell: TPoint; var CanSelect: Boolean); virtual;
|
|
procedure OnActiveSheetChanging(Sender: TcxCustomSpreadSheetBook;
|
|
const ActiveSheet: Integer; var CanSelect: Boolean); virtual;
|
|
procedure OnChangeCellData(Sender: TcxSSBookSheet; const ACol, ARow: Integer); virtual;
|
|
procedure OnChangeDefaultStyle(const AOldValue, ANewValue: TcxSSCellStyleRec); virtual;
|
|
procedure OnChangeLockColRow(Sender: TcxSSBookSheet; AKind: TcxSSHeaderType;
|
|
AIndex: Integer; AOldValue, ANewValue: Boolean); virtual;
|
|
procedure OnChangeSelection(Sender: TcxSSBookSheet;
|
|
const AOldValue, ANewValue: TRect); virtual;
|
|
procedure OnChangeSheetCaption(Sender: TcxSSBookSheet; var ACaption: string); virtual;
|
|
procedure OnChangeSizeColRow(Sender: TcxSSBookSheet; AKind: TcxSSHeaderType;
|
|
AIndex: Integer; var ANewSize: TcxSSSize); virtual;
|
|
procedure OnChangeVisibleColRow(Sender: TcxSSBookSheet; AKind: TcxSSHeadertype;
|
|
AIndex: Integer; AOldValue, ANewValue: Boolean); virtual;
|
|
procedure OnClearCells(Sender: TcxSSBookSheet; const ACellRec: TRect;
|
|
var AUseDefaultStyle, CanClear: Boolean); virtual;
|
|
procedure OnEditing(Sender: TcxSSBookSheet; const ACol, ARow: Integer;
|
|
var CanEdit: Boolean); virtual;
|
|
procedure OnDeleteCells(Sender: TcxSSBookSheet; ACellRect: TRect;
|
|
AModifyType: TcxSSModifyType); virtual;
|
|
procedure OnHistoryChanged(Sender: TObject); virtual;
|
|
procedure OnInsertCells(Sender: TcxSSBookSheet; ACellRect: TRect;
|
|
AModifyType: TcxSSModifyType); virtual;
|
|
procedure OnMergeCells(Sender: TcxSSBookSheet; ACellRect: TRect;
|
|
AIsMerge: Boolean; var CanMerge: Boolean); virtual;
|
|
procedure OnProgress(Sender: TObject; APercent: Byte); virtual;
|
|
procedure OnResizeDataLength(Sender: TcxSSBookSheet; AType: TcxSSHeaderType); virtual;
|
|
procedure OnSheetPopupMenu(Sender: TcxSSBookSheet;
|
|
const AHitPoint: TPoint); virtual;
|
|
procedure OnTopLeftChanging(Sender: TcxSSBookSheet; var ATopLeft: TPoint); virtual;
|
|
procedure OnCaptionPopupMenu(Sender: TcxSSBookSheet;
|
|
const AHitPoint: TPoint); virtual;
|
|
procedure UpdateAfterChanged(Sender: TcxSSBookSheet; ACellRect: TRect); virtual;
|
|
property LockRef: Integer read FLockCount;
|
|
public
|
|
constructor Create(AOwner: TcxCustomSpreadSheetBook); virtual;
|
|
property Owner: TcxCustomSpreadSheetBook read FOwner;
|
|
end;
|
|
|
|
{ TcxWorkBookControl }
|
|
TcxWorkBookSubControl = class(TInterfacedObject)
|
|
private
|
|
FBounds: TRect;
|
|
FOwner: TcxCustomSpreadSheetBook;
|
|
FVisible: Boolean;
|
|
function GetBoundsRect: TRect;
|
|
function GetCanvas: TcxCanvasWrapper;
|
|
function GetClientRect: TRect;
|
|
function GetControlCanvas: TCanvas;
|
|
function GetCursor: TCursor;
|
|
function GetHeight: Integer;
|
|
function GetLeft: Integer;
|
|
function GetTop: Integer;
|
|
function GetWidth: Integer;
|
|
procedure SetBoundsRect(ARect: TRect);
|
|
procedure SetCursor(const Value: TCursor);
|
|
procedure SetHeight(const Value: Integer);
|
|
procedure SetLeft(const Value: Integer);
|
|
procedure SetTop(const Value: Integer);
|
|
procedure SetVisible(const Value: Boolean);
|
|
procedure SetWidth(const Value: Integer);
|
|
protected
|
|
function ClientToScreen(const X, Y: Integer): TPoint;
|
|
procedure DblClick; virtual;
|
|
procedure FocusChanged; virtual;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); virtual;
|
|
procedure KeyPress(var Key: Char); virtual;
|
|
procedure KeyUp(var Key: Word; Shift: TShiftState); virtual;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); virtual;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); virtual;
|
|
procedure Paint; virtual;
|
|
procedure Resize; virtual;
|
|
procedure SetBounds(const ALeft, ATop, AWidth, AHeight: Integer);
|
|
procedure VisibleChanging; virtual;
|
|
property Canvas: TcxCanvasWrapper read GetCanvas;
|
|
property ControlCanvas: TCanvas read GetControlCanvas;
|
|
property BoundsRect: TRect read GetBoundsRect write SetBoundsRect;
|
|
property ClientRect: TRect read GetClientRect;
|
|
property Height: Integer read GetHeight write SetHeight;
|
|
property Left: Integer read GetLeft write SetLeft;
|
|
property Owner: TcxCustomSpreadSheetBook read FOwner;
|
|
property Top: Integer read GetTop write SetTop;
|
|
property Visible: Boolean read FVisible write SetVisible;
|
|
property Width: Integer read GetWidth write SetWidth;
|
|
property Cursor: TCursor read GetCursor write SetCursor;
|
|
public
|
|
constructor Create(AOwner: TcxCustomSpreadSheetBook); virtual;
|
|
procedure Invalidate; virtual;
|
|
procedure InvalidateRect(ARect: TRect);
|
|
end;
|
|
|
|
TcxSSBookPageCaptionsClass = class of TcxSSBookPageCaptions;
|
|
|
|
{ TcxSSBookPageCaptions }
|
|
TcxSSBookPageCaptions = class(TcxWorkBookSubControl)
|
|
private
|
|
FCaptionEditor: TcxSSInplaceTextEdit;
|
|
FCaptionPainter: TcxPageCaptionPainter;
|
|
FIsEditorActivate: Boolean;
|
|
FMouseDownPos: TPoint;
|
|
FSkipActivePageChanging: Boolean;
|
|
FViewInfo: TcxSSBookCaptionViewInfo;
|
|
function GetFirstVisibleCaption: Integer;
|
|
procedure SetFirstVisibleCaption(const Value: Integer);
|
|
protected
|
|
procedure ActivateEditor;
|
|
procedure DblClick; override;
|
|
procedure DoEditCaption; virtual;
|
|
function GetCaptionTextExtent(APage: Integer): TRect;
|
|
function HitTest(X, Y: Integer; var AIndex: Integer): TcxSSCaptionHitTest;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure OnEditCaptionText(Sender: TObject); virtual;
|
|
procedure OnEndEditCaption(Sender: TObject); virtual;
|
|
procedure Paint; override;
|
|
procedure ReCalcViewInfo; virtual;
|
|
procedure Resize; override;
|
|
procedure UpdateCaptionInfo(APage: Byte; AState: TcxSSCaptionStates); virtual;
|
|
procedure VisibleChanging; override;
|
|
property ViewInfo: TcxSSBookCaptionViewInfo read FViewInfo;
|
|
property PageCaptionPainter: TcxPageCaptionPainter read FCaptionPainter write FCaptionPainter;
|
|
public
|
|
property FirstVisibleCaption: Integer read GetFirstVisibleCaption write SetFirstVisibleCaption;
|
|
constructor Create(AOwner: TcxCustomSpreadSheetBook); override;
|
|
destructor Destroy; override;
|
|
procedure MakeTabVisible(AIndex: Integer);
|
|
end;
|
|
|
|
{ TcxSSCellObject }
|
|
TcxSSCellObject = class(TInterfacedObject, IcxSpreadSheetCell)
|
|
private
|
|
FCol: Integer;
|
|
FComplexAction: TcxComplexAction;
|
|
FCreatedStyle: TcxSSCellStyle;
|
|
FOwner: TcxSSDataStorage;
|
|
FAction: TcxCustomAction;
|
|
FRow: Integer;
|
|
function GetCellStyle: IcxSpreadSheetCellStyle;
|
|
function GetCellTextValue: string;
|
|
function GetCellValue: Variant;
|
|
function GetDataType: TcxSSDataType;
|
|
function GetDateTime: TDateTime;
|
|
function GetDisplayText: string;
|
|
function GetDisplayTextAlignment: TcxDisplayTextAlignment;
|
|
function GetIsLoading: Boolean;
|
|
function GetMergedRect: TRect;
|
|
function GetOwnerSheet: TcxSSBookSheet;
|
|
function GetStyle: TcxSSCellStyle;
|
|
function GetStyleExist: Boolean;
|
|
function GetText: string;
|
|
procedure SetDateTime(const Value: TDateTime);
|
|
procedure SetStyle(const Value: TcxSSCellStyle);
|
|
procedure SetText(const Value: string);
|
|
procedure SetTextEx(const Value: string; IsFormula: Boolean = False; Analyze: Boolean = True);
|
|
protected
|
|
procedure CheckCellWordBreak;
|
|
property Action: TcxCustomAction read FAction;
|
|
property ComplexAction: TcxComplexAction read FComplexAction;
|
|
property IsLoading: Boolean read GetIsLoading;
|
|
property Owner: TcxSSDataStorage read FOwner;
|
|
property OwnerSheet: TcxSSBookSheet read GetOwnerSheet;
|
|
property MergedRect: TRect read GetMergedRect;
|
|
public
|
|
constructor Create(AOwner: TcxSSDataStorage; ACol, ARow: Integer); virtual;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TcxSSCellObject); virtual;
|
|
procedure SetCellText(const AText: string; const NeedParse: Boolean = False);
|
|
property Col: Integer read FCol;
|
|
property DateTime: TDateTime read GetDateTime write SetDateTime;
|
|
property DataType: TcxSSDataType read GetDataType;
|
|
property DisplayText: string read GetDisplayText;
|
|
property DisplayTextAlignment: TcxDisplayTextAlignment read GetDisplayTextAlignment;
|
|
property Text: string read GetText write SetText;
|
|
property Row: Integer read FRow;
|
|
property CellValue: Variant read GetCellValue;
|
|
property Style: TcxSSCellStyle read GetStyle write SetStyle;
|
|
property StyleExist: Boolean read GetStyleExist;
|
|
end;
|
|
|
|
TcxSSSheetState = (ssResize, ssColHeader, ssRowHeader, ssEditorActivate, ssSelection);
|
|
TcxSSSheetStates = set of TcxSSSheetState;
|
|
|
|
{ TcxSSBookSheet }
|
|
TcxSSBookSheet = class(TcxWorkBookSubControl, IcxBookSheet)
|
|
private
|
|
FChangedSizeValue: TcxSSSize;
|
|
FCurrentPos: TPoint;
|
|
FDataStorage: TcxSSDataStorage;
|
|
FDownCellPos: TPoint;
|
|
FEditingPos: TPoint;
|
|
FIsEditMode: Boolean;
|
|
FMouseDownPos: TPoint;
|
|
FProtected: Boolean;
|
|
FReadOnly: Boolean;
|
|
FResizeHeaderType: TcxSSHeaderType;
|
|
FSheetViewInfo: TcxSSheetViewInfo;
|
|
FSheetState: TcxSSSheetStates;
|
|
FShowGrid: Boolean;
|
|
FShowHeaders: Boolean;
|
|
FShowFormulas: Boolean;
|
|
FSizeIndex: Integer;
|
|
FStartSelection: TPoint;
|
|
function GetActiveCell: TPoint;
|
|
function GetCell(const ACol, ARow: Integer): IcxSpreadSheetCell;
|
|
function GetCellEditor: TcxSSInplaceTextEdit;
|
|
function GetColHeader: TcxSSHeader;
|
|
function GetColumnCount: Integer;
|
|
function GetCorners: TRect;
|
|
function GetContentColCount: Integer;
|
|
function GetContentRowCount: Integer;
|
|
function GetCurrentCol: Integer;
|
|
function GetCurrentRow: Integer;
|
|
function GetHistory: TcxSpreadSheetHistory;
|
|
function GetIsLoaded: Boolean;
|
|
function GetListener: TcxSSListener;
|
|
function GetPageIndex: Integer;
|
|
function GetSheetCaption: string;
|
|
function GetRowCount: Integer;
|
|
function GetRowHeader: TcxSSHeader;
|
|
function GetSelectionRect: TRect;
|
|
function GetTopLeft: TPoint;
|
|
procedure SetActiveCell(const Value: TPoint);
|
|
procedure SetColRowSize(const AKind: TcxSSHeaderType;
|
|
const AColumn, ASize: Integer; ALocked: Boolean; AVisible: Boolean = True);
|
|
procedure SetCorners(const Value: TRect);
|
|
procedure SetDefaultSize(const AKind: TcxSSHeaderType; ASize: Integer);
|
|
procedure SetMergedCells(const ARect: TRect; IsMerge: Boolean);
|
|
procedure SetPageDimension(const AHorzCount, AVertCount: Integer);
|
|
procedure SetProtection(Value: Boolean);
|
|
procedure SetSheetCaption(Value: string);
|
|
procedure SetShowGrid(const Value: Boolean);
|
|
procedure SetShowHeaders(const Value: Boolean);
|
|
procedure SetShowFormulas(const Value: Boolean);
|
|
procedure SetSelectionRect(Value: TRect);
|
|
procedure SetTopLeft(const Value: TPoint);
|
|
procedure SetViewInformation(const ASelectionRect: TRect;
|
|
AViewFormulas, AViewGrid, AViewHeaders, AScrollBars: Boolean);
|
|
protected
|
|
procedure CellsChanged(const ARect: TRect); virtual;
|
|
procedure DblClick; override;
|
|
function DoEditorActivate: Boolean; virtual;
|
|
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; virtual;
|
|
procedure FocusChanged; override;
|
|
procedure InitScrollBars; virtual;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
procedure KeyUp(var Key: Word; Shift: TShiftState); override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure OnEndEditCell(Sender: TObject); virtual;
|
|
procedure Paint; override;
|
|
procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode;
|
|
var AScrollPos: Integer; IsViewInfoUpdate: Boolean = True); virtual;
|
|
function ViewInfoValid: Boolean;
|
|
property CurrentPos: TPoint read FCurrentPos;
|
|
property CellEditor: TcxSSInplaceTextEdit read GetCellEditor;
|
|
property DataStorage: TcxSSDataStorage read FDataStorage;
|
|
property IsEditMode: Boolean read FIsEditMode write FIsEditMode;
|
|
property IsLoaded: Boolean read GetIsLoaded;
|
|
property History: TcxSpreadSheetHistory read GetHistory;
|
|
property Listener: TcxSSListener read GetListener;
|
|
property TopLeft: TPoint read GetTopLeft write SetTopLeft;
|
|
property ViewInfo: TcxSSheetViewInfo read FSheetViewInfo;
|
|
public
|
|
constructor Create(AOwner: TcxCustomSpreadSheetBook); override;
|
|
destructor Destroy; override;
|
|
procedure ApplyAutoHeight(ARow: Integer); virtual;
|
|
procedure Assign(Source: TcxSSBookSheet); virtual;
|
|
procedure ClearAll; virtual;
|
|
procedure ClearCells(const ARect: TRect; SetDefaultStyle: Boolean = False);
|
|
procedure Copy(const ARect: TRect; IsCut: Boolean);
|
|
procedure DeleteCells(const ACells: TRect; ACellsModify: TcxSSCellsModify);
|
|
procedure FormatCells(const ACells: TRect);
|
|
function GetCellObject(ACol, ARow: Integer): TcxSSCellObject; virtual;
|
|
procedure InsertCells(const ACells: TRect; ACellsModify: TcxSSCellsModify);
|
|
procedure Invalidate; override;
|
|
procedure Paste(const APlace: TPoint);
|
|
procedure SelectCell(const ACol, ARow: Integer; OpenEditor: Boolean = False);
|
|
procedure SetMergedState(const ARect: TRect; IsMerge: Boolean);
|
|
procedure SetVisibleState(const ARect: TRect; ACols, ARows, AShow: Boolean);
|
|
procedure Sort(const ARect: TRect; const ASortTypes: array of TcxSortType);
|
|
property ActiveCell: TPoint read GetActiveCell write SetActiveCell;
|
|
property Caption: string read GetSheetCaption write SetSheetCaption;
|
|
property Col: Integer read GetCurrentCol;
|
|
property Cols: TcxSSHeader read GetColHeader;
|
|
property ColumnCount: Integer read GetColumnCount;
|
|
property Corners: TRect read GetCorners write SetCorners;
|
|
property ContentColCount: Integer read GetContentColCount;
|
|
property ContentRowCount: Integer read GetContentRowCount;
|
|
property PageIndex: Integer read GetPageIndex;
|
|
property Protected: Boolean read FProtected write FProtected;
|
|
property ReadOnly: Boolean read FReadOnly write FReadOnly;
|
|
property Row: Integer read GetCurrentRow;
|
|
property Rows: TcxSSHeader read GetRowHeader;
|
|
property RowCount: Integer read GetRowCount;
|
|
property SelectionRect: TRect read GetSelectionRect write SetSelectionRect;
|
|
property ShowGrid: Boolean read FShowGrid write SetShowGrid;
|
|
property ShowHeaders: Boolean read FShowHeaders write SetShowHeaders;
|
|
property ShowFormulas: Boolean read FShowFormulas write SetShowFormulas;
|
|
end;
|
|
|
|
TcxSSActiveCellChangingEvent = procedure(Sender: TcxSSBookSheet;
|
|
const ActiveCell: TPoint; var CanSelect: Boolean) of object;
|
|
TcxSSActiveSheetChangingEvent = procedure(Sender: TcxCustomSpreadSheetBook;
|
|
const ActiveSheet: Integer; var CanSelect: Boolean) of object;
|
|
TcxSSCellChangeEvent = procedure(Sender: TcxSSBookSheet; const ACol, ARow: Integer) of object;
|
|
TcxSSClearCellsEvent = procedure(Sender: TcxSSBookSheet; const ACellRect: TRect;
|
|
var UseDefaultStyle, CanClear: Boolean) of object;
|
|
TcxSSCustomPaintEvent = procedure (Sender: TObject;
|
|
var PainterClass: TcxSheetPainterClass) of object;
|
|
TcxSSDeleteSheetEvent = procedure(const ASheet: Integer; var CanDelete: Boolean) of object;
|
|
TcxSSExchangeSheetsEvent = procedure(const ASheet1, ASheet2: Integer; var CanExchange: Boolean) of object;
|
|
TcxSSSetSelectionEvent = procedure (Sender: TObject; ASheet: TcxSSBookSheet) of object;
|
|
TcxSSSetPositionEvent = procedure (Sender: TObject; ASheet: TcxSSBookSheet) of object;
|
|
TcxSSChangeVisible = procedure (Sender: TObject; ASheet: TcxSSBookSheet;
|
|
AChangedIndex: Integer; APrevValue, ANewValue: Boolean) of object;
|
|
TcxSSPopupMenuEvent = procedure (Sender: TObject; X, Y: Integer) of object;
|
|
TcxSSResizeEvent = procedure(Sender: TcxSSBookSheet;
|
|
AIndex: Integer; var ANewSize: TcxSSSize) of object;
|
|
TcxSSFormatCellsEvent = procedure(Sender: TObject; var ACells: TRect;
|
|
var CanFormat: Boolean; out FormatDialogClass: TcxSSFormatDialogClass) of object;
|
|
TcxSSTopLeftChangingEvent = procedure(Sender: TcxSSBookSheet; var ATopLeft: TPoint) of object;
|
|
TcxSSMergeCellsEvent = procedure(Sender: TcxSSBookSheet; ACellRect: TRect;
|
|
AIsMerge: Boolean; var CanMerge: Boolean) of object;
|
|
TcxSSChangeCaptionEvent = procedure(Sender: TcxSSBookSheet; var ACaption: string) of object;
|
|
TcxSSEditingEvent = procedure(Sender: TcxSSBookSheet; const ACol, ARow: Integer;
|
|
var CanEdit: Boolean) of object;
|
|
{$IFNDEF DELPHI5}
|
|
TcxSSContextPopupEvent = procedure(Sender: TObject; MousePos: TPoint; var Handled: Boolean) of object;
|
|
{$ENDIF}
|
|
|
|
{ TcxCustomSpreadSheetBook }
|
|
TcxCustomSpreadSheetBook = class(TcxControl, IUnknown, IcxSpreadSheetBook)
|
|
private
|
|
FTimer: TTimer;
|
|
FActivePage: Integer;
|
|
FBufferedPaint: Boolean;
|
|
FCanvas: TcxCanvasWrapper;
|
|
FCaptionBar: TcxSSBookPageCaptions;
|
|
FCaptureControl: TcxWorkBookSubControl;
|
|
FCellEditor: TcxSSInplaceTextEdit;
|
|
FColHeaderHeight: Integer;
|
|
FContextPopupHandled: Boolean;
|
|
FDefaultColWidth: TcxSSSize;
|
|
FDefaultRowHeight: TcxSSSize;
|
|
FFormulasCache: TcxSSFormulasCache;
|
|
FFloatPrecision: Byte;
|
|
FGridColor: TColor;
|
|
FHeaderColor: TColor;
|
|
FHeaderFont: TFont;
|
|
FHistory: TcxSpreadSheetHistory;
|
|
FHideSelection: Boolean;
|
|
FIsLoaded: Boolean;
|
|
FListener: TcxSSListener;
|
|
FProtected: Boolean;
|
|
FMouseDownPos: TPoint;
|
|
FMousePos: TPoint;
|
|
FModified: Boolean;
|
|
FPainter: TcxSheetPainter;
|
|
FPaintBitmap: TBitmap;
|
|
FPainterType: TcxSSPainterType;
|
|
FPages: TList;
|
|
FPageVisible: array of Boolean;
|
|
FPalette: TcxExcelPalette;
|
|
FReadOnly: Boolean;
|
|
FRowHeaderWidth: Integer;
|
|
FRowsAutoHeight: Boolean;
|
|
FScrollBars: TcxScrollBars;
|
|
FSelectionColor: TColor;
|
|
FShift: TShiftState;
|
|
FShowCaptionBar: Boolean;
|
|
FShowFormulas: Boolean;
|
|
FShowGrid: Boolean;
|
|
FStyleCache: TcxSSStyleCache;
|
|
FWindowColor: TColor;
|
|
FOnActiveCellChanging: TcxSSActiveCellChangingEvent;
|
|
FOnActiveSheetChanging: TcxSSActiveSheetChangingEvent;
|
|
FOnAfterCalculation: TNotifyEvent;
|
|
FOnCaptionPopupMenu: TcxSSPopupMenuEvent;
|
|
FOnCellChange: TcxSSCellChangeEvent;
|
|
FOnClearCells: TcxSSClearCellsEvent;
|
|
FOnChangeColVisible: TcxSSChangeVisible;
|
|
FOnChangeCaption: TcxSSChangeCaptionEvent;
|
|
FOnChangeRowVisible: TcxSSChangeVisible;
|
|
{$IFNDEF DELPHI5}
|
|
FOnContextPopup: TcxSSContextPopupEvent;
|
|
{$ENDIF}
|
|
FOnCustomPaint: TcxSSCustomPaintEvent;
|
|
FOnEditing: TcxSSEditingEvent;
|
|
FOnEndEdit: TNotifyEvent;
|
|
FOnFormatCells: TcxSSFormatCellsEvent;
|
|
FOnHistoryChanged: TNotifyEvent;
|
|
FOnMergeCells: TcxSSMergeCellsEvent;
|
|
FOnProgress: TcxProgressEvent;
|
|
FOnResizeCol: TcxSSResizeEvent;
|
|
FOnResizeRow: TcxSSResizeEvent;
|
|
FOnSetSelection: TcxSSSetSelectionEvent;
|
|
FOnSheetPopupMenu: TcxSSPopupMenuEvent;
|
|
FOnTopLeftChanging: TcxSSTopLeftChangingEvent;
|
|
FExcelProtectionStyle: Boolean;
|
|
function AddSheet(const AName: string; AVisible: Boolean): IcxBookSheet;
|
|
function GetActiveCell: TPoint;
|
|
function GetActiveSheet: TcxSSBookSheet;
|
|
function GetAutoReCalc: Boolean;
|
|
function GetCell(APage: Word; ACol, ARow: Integer): IcxSpreadSheetCell;
|
|
function GetDefinedNames: TcxSSNamesDef;
|
|
function GetDefaultStyle: TcxSSDefaultStyle;
|
|
function GetPage(APage: Integer): TcxSSBookSheet;
|
|
function GetPageCount: Word;
|
|
function GetPageSelection(APage: Word): TRect;
|
|
function GetPageVisible(APage: Word): Boolean;
|
|
function GetRCRefStyle: Boolean;
|
|
function GetSelection: TRect;
|
|
function GetSheet(APage: Word): IcxBookSheet;
|
|
function GetShowHeaders: Boolean;
|
|
procedure SetActiveCell(const AValue: TPoint);
|
|
procedure SetActivePage(AValue: Integer);
|
|
procedure SetAutoRecalc(const AValue: Boolean);
|
|
procedure SetBufferedPaint(const AValue: Boolean);
|
|
procedure SetColHeaderHeight(const AValue: Integer);
|
|
procedure SetCustomPainter(const AValue: TcxSSCustomPaintEvent);
|
|
procedure SetDefaultColWidth(const AValue: TcxSSSize);
|
|
procedure SetDefaultStyle(const AStyle: PcxSSCellStyleRec);
|
|
procedure SetDefaultStyleProperty(AValue: TcxSSDefaultStyle);
|
|
procedure SetDefaultRowHeight(const AValue: TcxSSSize);
|
|
procedure SetDefaultColor(const AValue: TColor);
|
|
procedure SetFloatPrecision(const AValue: Byte);
|
|
procedure SetGridColor(const AValue: TColor);
|
|
procedure SetHeaderFont(AValue: TFont);
|
|
procedure SetHeaderColor(const AValue: TColor);
|
|
procedure SetPainterType(const AValue: TcxSSPainterType);
|
|
procedure SetPageCount(const AValue: Word);
|
|
procedure SetPageSelection(APage: Word; const AValue: TRect);
|
|
procedure SetPageVisible(APage: Word; const AValue: Boolean);
|
|
procedure SetPalette(const APalette: PcxExcelPalette);
|
|
procedure SetProtection(Value: Boolean);
|
|
procedure SetRCRefStyle(const AValue: Boolean);
|
|
procedure SetReadOnly(const AValue: Boolean);
|
|
procedure SetRowHeaderWidth(const AValue: Integer);
|
|
procedure SetSelectionColor(const AValue: TColor);
|
|
procedure SetScrollBars(const AValue: TcxScrollBars);
|
|
procedure SetShowCaptionBar(const AValue: Boolean);
|
|
procedure SetShowFormulas(const AValue: Boolean);
|
|
procedure SetShowHeaders(const AValue: Boolean);
|
|
procedure SetShowGrid(const AValue: Boolean);
|
|
procedure SetSelection(const AValue: TRect);
|
|
procedure CM_CHANGELOCALE(var Message: TMessage); message CM_WININICHANGE;
|
|
{$IFNDEF DELPHI5}
|
|
procedure WMRButtonUp(var Message: TWMRButtonUp); message WM_RBUTTONUP;
|
|
{$ENDIF}
|
|
protected
|
|
IsDataLoading: Boolean;
|
|
procedure AddPage(ASheet: TcxSSBookSheet); virtual;
|
|
procedure AddSheetPage(const APageName: string = ''); virtual;
|
|
procedure AdjustControls; virtual;
|
|
procedure DblClick; override;
|
|
procedure DoRecalc;
|
|
function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
|
|
MousePos: TPoint): Boolean; override;
|
|
{$IFDEF DELPHI5}
|
|
procedure DoContextPopup( MousePos: TPoint; var Handled: Boolean); override;
|
|
{$ENDIF}
|
|
procedure FocusChanged; override;
|
|
function GetBookPageCaptionsClass: TcxSSBookPageCaptionsClass;
|
|
function GetCaptionPainterClass: TcxPageCaptionPainterClass; virtual;
|
|
function GetDataStorageClass: TcxSSDataStorageClass; virtual;
|
|
function GetFormulasCacheClass: TcxFormulasCacheClass; virtual;
|
|
function GetHeaderClass: TcxSSHeaderClass; virtual;
|
|
function GetHistoryClass: TcxSSHistoryClass; virtual;
|
|
function GetHScrollBarBounds: TRect; override;
|
|
function GetInplaceEditClass: TcxSSInplaceEditClass; virtual;
|
|
function GetListenerClass: TcxSSListenerClass; virtual;
|
|
function GetPainterClass: TcxSheetPainterClass; virtual;
|
|
function GetPalettePtr: PcxExcelPalette;
|
|
function GetStyleCacheClass: TcxSSStyleCacheClass; virtual;
|
|
function GetSheetClass: TcxSSBookSheetClass; virtual;
|
|
function GetVScrollBarBounds: TRect; override;
|
|
function GetViewInfoClass: TcxSSheetViewInfoClass; virtual;
|
|
procedure InitScrollBarsParameters; override;
|
|
procedure InternalUpdate; virtual;
|
|
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
|
|
procedure KeyPress(var Key: Char); override;
|
|
procedure KeyUp(var Key: Word; Shift: TShiftState); override;
|
|
procedure Loaded; override;
|
|
procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
|
|
procedure OnChangeHeaderStyle(Sender: TObject); virtual;
|
|
procedure OnMouseTimerHandle(Sender: TObject); virtual;
|
|
procedure Paint; override;
|
|
procedure Resize; override;
|
|
procedure Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode;
|
|
var AScrollPos: Integer); override;
|
|
function SpreadSheetClipboardDataToData(ASheet: TcxSSBookSheet;
|
|
const AColPos, ARowPos: Integer; out AChangedRect: TRect): Boolean; virtual;
|
|
function SpreadSheetDataToClipboardData(ASheet: TcxSSBookSheet;
|
|
const ACells: TRect): AnsiString; virtual;
|
|
procedure SetModified;
|
|
procedure VisibleChanging; override;
|
|
function ViewInfoValid: Boolean;
|
|
property ActiveCell: TPoint read GetActiveCell write SetActiveCell;
|
|
property ActivePage: Integer read FActivePage write SetActivePage;
|
|
property ActiveSheet: TcxSSBookSheet read GetActiveSheet;
|
|
property AutoRecalc: Boolean read GetAutoRecalc write SetAutoRecalc default True;
|
|
property CaptureControl: TcxWorkBookSubControl read FCaptureControl;
|
|
property ColHeaderHeight: Integer read FColHeaderHeight write SetColHeaderHeight default 20;
|
|
property CaptionBar: TcxSSBookPageCaptions read FCaptionBar;
|
|
property Canvas: TcxCanvasWrapper read FCanvas;
|
|
property DefaultColWidth: TcxSSSize read FDefaultColWidth write SetDefaultColWidth default 85;
|
|
property DefaultRowHeight: TcxSSSize read FDefaultRowHeight write SetDefaultRowHeight default 20;
|
|
property DefaultStyle: TcxSSDefaultStyle read GetDefaultStyle write SetDefaultStyleProperty;
|
|
property DefinedNames: TcxSSNamesDef read GetDefinedNames;
|
|
property FormulasCache: TcxSSFormulasCache read FFormulasCache;
|
|
property GridColor: TColor read FGridColor write SetGridColor default clBtnFace;
|
|
property HeaderColor: TColor read FHeaderColor write SetHeaderColor default clBtnFace;
|
|
property HeaderFont: TFont read FHeaderFont write SetHeaderFont;
|
|
property History: TcxSpreadSheetHistory read FHistory;
|
|
property IsLoaded: Boolean read FIsLoaded;
|
|
property Listener: TcxSSListener read FListener;
|
|
property PageCount: Word read GetPageCount write SetPageCount default 1;
|
|
property PageSelection[APage: Word]: TRect read GetPageSelection write SetPageSelection;
|
|
property Pages[APage: Integer]: TcxSSBookSheet read GetPage; default;
|
|
property PageVisible[APage: Word]: Boolean read GetPageVisible write SetPageVisible;
|
|
property PaintBitmap: TBitmap read FPaintBitmap;
|
|
property Painter: TcxSheetPainter read FPainter;
|
|
property PainterType: TcxSSPainterType read FPainterType write SetPainterType default ptOffice97Style;
|
|
property Palette: PcxExcelPalette read GetPalettePtr;
|
|
property Precision: Byte read FFloatPrecision write SetFloatPrecision default 2;
|
|
property RowHeaderWidth: Integer read FRowHeaderWidth write SetRowHeaderWidth default 85;
|
|
property SelectionColor: TColor read FSelectionColor write SetSelectionColor default clHighLight;
|
|
property StyleCache: TcxSSStyleCache read FStyleCache;
|
|
property ShowCaptionBar: Boolean read FShowCaptionBar write SetShowCaptionBar default True;
|
|
property ShowFormulas: Boolean read FShowFormulas write SetShowFormulas default False;
|
|
property ShowGrid: Boolean read FShowGrid write SetShowGrid default True;
|
|
property ShowHeaders: Boolean read GetShowHeaders write SetShowHeaders default True;
|
|
property SelectionRect: TRect read GetSelection write SetSelection;
|
|
property OnActiveCellChanging: TcxSSActiveCellChangingEvent read FOnActiveCellChanging
|
|
write FOnActiveCellChanging;
|
|
property OnActiveSheetChanging: TcxSSActiveSheetChangingEvent read FOnActiveSheetChanging
|
|
write FOnActiveSheetChanging;
|
|
property OnAfterCalculation: TNotifyEvent read FOnAfterCalculation write FOnAfterCalculation;
|
|
property OnChangeColVisible: TcxSSChangeVisible read FOnChangeColVisible
|
|
write FOnChangeColVisible;
|
|
property OnChangeSheetCaption: TcxSSChangeCaptionEvent read FonChangeCaption write FonChangeCaption;
|
|
property OnChangeRowVisible: TcxSSChangeVisible read FOnChangeRowVisible
|
|
write FOnChangeRowVisible;
|
|
property OnCellChange: TcxSSCellChangeEvent read FOnCellChange write FOnCellChange;
|
|
property OnClearCells: TcxSSClearCellsEvent read FOnClearCells write FOnClearCells;
|
|
{$IFNDEF DELPHI5}
|
|
property OnContextPopup: TcxSSContextPopupEvent read FOnContextPopup write FOnContextPopup;
|
|
{$ENDIF}
|
|
property OnCustomPaint: TcxSSCustomPaintEvent read FOnCustomPaint write SetCustomPainter;
|
|
property OnEditing: TcxSSEditingEvent read FOnEditing write FOnEditing;
|
|
property OnEndEdit: TNotifyEvent read FOnEndEdit write FOnEndEdit;
|
|
property OnFormatCells: TcxSSFormatCellsEvent read FOnFormatCells write FOnFormatCells;
|
|
property OnHistoryChanged: TNotifyEvent read FOnHistoryChanged write FOnHistoryChanged;
|
|
property OnMergeCells: TcxSSMergeCellsEvent read FOnMergeCells write FOnMergeCells;
|
|
property OnProgress: TcxProgressEvent read FOnProgress write FOnProgress;
|
|
property OnResizeCol: TcxSSResizeEvent read FOnResizeCol write FOnResizeCol;
|
|
property OnResizeRow: TcxSSResizeEvent read FOnResizeRow write FOnResizeRow;
|
|
property OnSetSelection: TcxSSSetSelectionEvent read FOnSetSelection write FOnSetSelection;
|
|
property OnSheetPopupMenu: TcxSSPopupMenuEvent read FOnSheetPopupMenu write FOnSheetPopupMenu;
|
|
property OnCaptionPopupMenu: TcxSSPopupMenuEvent read FOnCaptionPopupMenu write FOnCaptionPopupMenu;
|
|
property OnTopLeftChanging: TcxSSTopLeftChangingEvent read FOnTopLeftChanging write FOnTopLeftChanging;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure Assign(Source: TPersistent); override;
|
|
function BeginUpdate: Integer;
|
|
function CellsNameByRef(ASheet: Integer; const CellsRef: TRect; IsText: Boolean = True): string;
|
|
procedure ClearAll;
|
|
procedure DeactivateEditor;
|
|
function DeleteName(const AName: string): Boolean; virtual;
|
|
function DefineName(const AName: string; APage: Word; const ARect: TRect): Integer; virtual;
|
|
function DefineNameEx(const AName: string; APage: Word; const ARect: TRect; Validate: Boolean = True): Integer; virtual;
|
|
function EndUpdate: Integer;
|
|
function HasRectName(ASheet: Integer; const ARect: TRect): Integer;
|
|
function HitTest(const APoint: TPoint;
|
|
out HitTestInfo: TcxSSHitTestInfo): Boolean; virtual;
|
|
procedure LoadFromFile(const AFileName: string); virtual;
|
|
procedure LoadFromStream(Stream: TStream); virtual;
|
|
procedure Recalc; virtual;
|
|
procedure SaveToFile(const AFileName: string); virtual;
|
|
procedure SaveToStream(AStream: TStream); virtual;
|
|
procedure UpdateControl; virtual;
|
|
property DocumentModified: Boolean read FModified;
|
|
published
|
|
property BufferedPaint: Boolean read FBufferedPaint write SetBufferedPaint default False;
|
|
property ExcelProtectionStyle: Boolean read FExcelProtectionStyle write FExcelProtectionStyle default True;
|
|
property HideSelection: Boolean read FHideSelection write FHideSelection default False;
|
|
property R1C1ReferenceStyle: Boolean read GetRCRefStyle write SetRCRefStyle default False;
|
|
property RowsAutoHeight: Boolean read FRowsAutoHeight write FRowsAutoHeight default True;
|
|
property ScrollBars: TcxScrollBars read FScrollBars write SetScrollBars default sbsBoth;
|
|
property BackgroundColor: TColor read FWindowColor write SetDefaultColor default clWindow;
|
|
property ReadOnly: Boolean read FReadOnly write SetReadOnly default False;
|
|
property Protected: Boolean read FProtected write FProtected default False;
|
|
property Visible;
|
|
end;
|
|
|
|
{ TcxSSFormatDialog }
|
|
TcxSSFormatDialog = class(TForm)
|
|
public
|
|
{$IFDEF DELPHI9}
|
|
constructor Create(AOwner: TComponent); override;
|
|
{$ENDIF}
|
|
function Execute(const ACells: TRect; ASheet: TcxSSBookSheet): Boolean; virtual;
|
|
published
|
|
property Position default poDesigned;
|
|
end;
|
|
|
|
{ TcxSpreadSheetBook }
|
|
TcxSpreadSheetBook = class(TcxCustomSpreadSheetBook)
|
|
private
|
|
FOnDeleteSheet: TcxSSDeleteSheetEvent;
|
|
FOnExchangeSheets: TcxSSExchangeSheetsEvent;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
procedure AddSheetPage(const APageName: string = ''); override;
|
|
procedure EditActiveSheetCaption;
|
|
procedure ExchangeSheets(const ASheet1, ASheet2: Integer); virtual;
|
|
procedure DeleteSheet(const ASheet: Integer); virtual;
|
|
property ActiveCell;
|
|
property ActivePage;
|
|
property ActiveSheet;
|
|
property DefinedNames;
|
|
property History;
|
|
property Palette;
|
|
property Pages;
|
|
property PageVisible;
|
|
property SelectionRect;
|
|
published
|
|
property Align;
|
|
property Anchors;
|
|
property AutoRecalc;
|
|
property ColHeaderHeight;
|
|
property DefaultStyle;
|
|
property DefaultColWidth;
|
|
property DefaultRowHeight;
|
|
property GridColor;
|
|
property HeaderFont;
|
|
property HeaderColor;
|
|
property PainterType;
|
|
property Precision;
|
|
property PageCount;
|
|
property PopupMenu;
|
|
property RowHeaderWidth;
|
|
property SelectionColor;
|
|
property ShowCaptionBar;
|
|
property ShowFormulas;
|
|
property ShowGrid;
|
|
property ShowHeaders;
|
|
property OnDeleteSheet: TcxSSDeleteSheetEvent read FOnDeleteSheet write FOnDeleteSheet;
|
|
property OnExchangeSheets: TcxSSExchangeSheetsEvent read FOnExchangeSheets write FOnExchangeSheets;
|
|
property OnActiveCellChanging;
|
|
property OnActiveSheetChanging;
|
|
property OnAfterCalculation;
|
|
property OnCellChange;
|
|
property OnChangeColVisible;
|
|
property OnChangeSheetCaption;
|
|
property OnChangeRowVisible;
|
|
property OnClearCells;
|
|
property OnCustomPaint;
|
|
property OnEditing;
|
|
property OnEndEdit;
|
|
property OnFormatCells;
|
|
property OnHistoryChanged;
|
|
property OnMergeCells;
|
|
property OnProgress;
|
|
property OnResizeCol;
|
|
property OnResizeRow;
|
|
property OnSetSelection;
|
|
property OnSheetPopupMenu;
|
|
property OnCaptionPopupMenu;
|
|
property OnTopLeftChanging;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnClick;
|
|
property OnContextPopup;
|
|
property OnDblClick;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnResize;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
end;
|
|
|
|
{ TcxSpreadSheet }
|
|
TcxSpreadSheet = class(TcxCustomSpreadSheetBook)
|
|
private
|
|
function GetSheet: TcxSSBookSheet;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
property Sheet: TcxSSBookSheet read GetSheet;
|
|
property ActiveCell;
|
|
property History;
|
|
property DefinedNames;
|
|
property Palette;
|
|
property SelectionRect;
|
|
published
|
|
property Align;
|
|
property Anchors;
|
|
property AutoRecalc;
|
|
property ColHeaderHeight;
|
|
property DefaultStyle;
|
|
property DefaultColWidth;
|
|
property DefaultRowHeight;
|
|
property GridColor;
|
|
property HeaderFont;
|
|
property HeaderColor;
|
|
property PainterType;
|
|
property Precision;
|
|
property RowHeaderWidth;
|
|
property SelectionColor;
|
|
property ShowFormulas;
|
|
property ShowGrid;
|
|
property ShowHeaders;
|
|
property OnActiveCellChanging;
|
|
property OnAfterCalculation;
|
|
property OnCellChange;
|
|
property OnChangeColVisible;
|
|
property OnChangeRowVisible;
|
|
property OnClearCells;
|
|
property OnCustomPaint;
|
|
property OnEditing;
|
|
property OnEndEdit;
|
|
property OnFormatCells;
|
|
property OnHistoryChanged;
|
|
property OnMergeCells;
|
|
property OnProgress;
|
|
property OnResizeCol;
|
|
property OnResizeRow;
|
|
property OnSetSelection;
|
|
property OnSheetPopupMenu;
|
|
property OnTopLeftChanging;
|
|
property OnEnter;
|
|
property OnExit;
|
|
property OnClick;
|
|
property OnContextPopup;
|
|
property OnDblClick;
|
|
property OnMouseDown;
|
|
property OnMouseMove;
|
|
property OnMouseUp;
|
|
property OnResize;
|
|
property OnKeyDown;
|
|
property OnKeyPress;
|
|
property OnKeyUp;
|
|
end;
|
|
|
|
{ TcxSSClipboard }
|
|
TcxSSClipboard = class
|
|
private
|
|
function GetESSData: AnsiString;
|
|
function GetUnicodeData: WideString;
|
|
procedure SetUnicodeData(const Value: WideString);
|
|
procedure SetESSData(const Value: AnsiString);
|
|
protected
|
|
function BufferSize(AFormat: Word): Integer;
|
|
procedure GetBuffer(AFormat: Word; var ABuffer);
|
|
procedure SetBuffer(AFormat: Word; const ABuffer; ASize: Integer; ClearClipboard: Boolean);
|
|
public
|
|
property DataAsUnicode: WideString read GetUnicodeData write SetUnicodeData;
|
|
property DataAsEssFormat: AnsiString read GetESSData write SetEssData;
|
|
end;
|
|
|
|
function CanModify(ABook, ASheet: TObject; ACol, ARow: Integer): Boolean; overload;
|
|
function CanModify(ABook, ASheet: TObject; const ARect: TRect): Boolean; overload;
|
|
function CellReadOnly(ABook, ASheet: TObject; ACol, ARow: Integer): Boolean;
|
|
|
|
implementation
|
|
|
|
uses
|
|
cxSSDesigner, cxLibraryConsts;
|
|
|
|
{$R *.res}
|
|
|
|
type
|
|
TcxHeaderAccess = class(TcxSSHeader);
|
|
TcxHistoryAccess = class(TcxSpreadSheetHistory);
|
|
TcxDataStorageAccess = class(TcxSSDataStorage);
|
|
TcxFormulasAccess = class(TcxSSFormulasCache);
|
|
TcxStyleAccess = class(TcxSSCellStyle);
|
|
TCustomControlAccess = class(TCustomControl);
|
|
TWinControlAccess = class(TWinControl);
|
|
|
|
var
|
|
cxSSClipboard: TcxSSClipboard;
|
|
CF_ESSDATA: Integer;
|
|
|
|
const
|
|
SCF_ESSCLIPBOARDFORMAT = 'ExpressSpreadSheet 1.0';
|
|
CellTerminator = #9;
|
|
RowTerminator = #13#10;
|
|
|
|
cxHScrollHeight: Integer = 16;
|
|
cxVScrollWidth: Integer = 16;
|
|
ScrollersVisible: array[TcxScrollBars, TScrollBarKind] of Boolean =
|
|
((False, False), (True, False), (False, True), (True, True));
|
|
|
|
function OrdinalToFormatStr(const AString: string; AFormat: TxlsDataFormat; ADig: Byte): string;
|
|
var
|
|
AFValue: Double;
|
|
ABValue: Boolean;
|
|
AColor: Word;
|
|
begin
|
|
Result := AString;
|
|
if AFormat <> $31 then
|
|
begin
|
|
if cxTryStrToFloat(AString, AFValue) then
|
|
Result := TcxSSUtils.FormatText(AFValue, AFormat, ADig, AColor)
|
|
else
|
|
if cxTryStrToBool(AString, ABValue) then
|
|
Result := TcxSSUtils.FormatText(Byte(ABValue), AFormat, ADig, AColor)
|
|
end;
|
|
end;
|
|
|
|
function CellReadOnly(ABook, ASheet: TObject; ACol, ARow: Integer): Boolean;
|
|
var
|
|
Wb: TcxCustomSpreadSheetBook;
|
|
Sh: TcxSSBookSheet;
|
|
AHasCell: Boolean;
|
|
AState: TcxSSCellStates;
|
|
begin
|
|
Wb := TcxCustomSpreadSheetBook(ABook);
|
|
Sh := TcxSSBookSheet(ASheet);
|
|
Result := not Wb.IsDataLoading;
|
|
if not Result then Exit;
|
|
AState := Sh.DataStorage.Cells[ACol, ARow].StylePtr^.CellState;
|
|
AHasCell := Sh.DataStorage.HasCell(ACol, ARow);
|
|
if Wb.ExcelProtectionStyle then
|
|
begin
|
|
Result := Wb.Protected or Sh.Protected;
|
|
if Result then
|
|
begin
|
|
if AHasCell then
|
|
Result := cLocked in AState
|
|
else
|
|
Result := Sh.Cols.LockProtect[ACol];
|
|
end;
|
|
end
|
|
else
|
|
Result := Wb.ReadOnly or Sh.ReadOnly or (cReadOnly in AState);
|
|
end;
|
|
|
|
function CanModify(ABook, ASheet: TObject; ACol, ARow: Integer): Boolean;
|
|
begin
|
|
Result := not CellReadOnly(ABook, ASheet, ACol, ARow);
|
|
end;
|
|
|
|
function CanModify(ABook, ASheet: TObject; const ARect: TRect): Boolean;
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
Result := True;
|
|
for I := ARect.Left to ARect.Right do
|
|
for J := ARect.Top to ARect.Bottom do
|
|
begin
|
|
Result := Result and CanModify(ABook, ASheet, I, J);
|
|
if not Result then Exit;
|
|
end;
|
|
end;
|
|
|
|
{ TcxSpreadSheetBook }
|
|
constructor TcxSpreadSheetBook.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
AddSheetPage;
|
|
end;
|
|
|
|
procedure TcxSpreadSheetBook.AddSheetPage(const APageName: string = '');
|
|
begin
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxSpreadSheetBook.EditActiveSheetCaption;
|
|
begin
|
|
FCaptionBar.DoEditCaption;
|
|
end;
|
|
|
|
procedure TcxSpreadSheetBook.ExchangeSheets(const ASheet1, ASheet2: Integer);
|
|
var
|
|
ACanExchange: Boolean;
|
|
begin
|
|
if (ASheet1 > PageCount) or (ASheet2 > PageCount) then Exit;
|
|
if Assigned(FOnExchangeSheets) then
|
|
begin
|
|
ACanExchange := True;
|
|
FOnExchangeSheets(ASheet1, ASheet2, ACanExchange);
|
|
if not ACanExchange then Exit;
|
|
end;
|
|
FPages.Exchange(ASheet1, ASheet2);
|
|
if ASheet1 = FActivePage then
|
|
FActivePage := ASheet2
|
|
else
|
|
if ASheet2 = FActivePage then
|
|
FActivePage := ASheet1;
|
|
FormulasCache.UpdateOnExchangeSheets(ASheet1, ASheet2);
|
|
FCaptionBar.ReCalcViewInfo;
|
|
FCaptionBar.Invalidate;
|
|
Recalc;
|
|
end;
|
|
|
|
procedure TcxSpreadSheetBook.DeleteSheet(const ASheet: Integer);
|
|
var
|
|
ACanDelete: Boolean;
|
|
AIndex, I: Integer;
|
|
begin
|
|
if (ASheet >= PageCount) or (ASheet < 0) or (PageCount = 1) then Exit;
|
|
if Assigned(FOnDeleteSheet) then
|
|
begin
|
|
ACanDelete := True;
|
|
FOnDeleteSheet(ASheet, ACanDelete);
|
|
if not ACanDelete then Exit;
|
|
end;
|
|
|
|
AIndex := -1;
|
|
for I := PageCount - 1 downto 0 do
|
|
begin
|
|
if ((AIndex < 0) or (AIndex > ASheet)) and (I <> ASheet) and PageVisible[I] then
|
|
AIndex := I;
|
|
end;
|
|
if AIndex = -1 then
|
|
raise ESpreadSheetError.Create(cxGetResourceString(@scxSpreadSheetDeleteLastSheet));
|
|
|
|
SetActivePage(AIndex);
|
|
if FActivePage > ASheet then
|
|
Dec(FActivePage);
|
|
|
|
TcxSSBookSheet(FPages[ASheet])._Release;
|
|
FPages.Delete(ASheet);
|
|
if ASheet < PageCount then
|
|
System.Move(FPageVisible[ASheet + 1], FPageVisible[ASheet],
|
|
(PageCount - ASheet) * SizeOf(Boolean));
|
|
SetLength(FPageVisible, Length(FPageVisible) - 1);
|
|
FormulasCache.UpdateOnDeleteSheet(ASheet);
|
|
if FCaptionBar.FirstVisibleCaption >= PageCount then
|
|
FCaptionBar.FirstVisibleCaption := PageCount - 1;
|
|
FCaptionBar.ReCalcViewInfo;
|
|
UpdateControl;
|
|
end;
|
|
|
|
{ TcxSpreadSheet }
|
|
constructor TcxSpreadSheet.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
ShowCaptionBar := False;
|
|
AddSheetPage;
|
|
end;
|
|
|
|
function TcxSpreadSheet.GetSheet: TcxSSBookSheet;
|
|
begin
|
|
Result := ActiveSheet;
|
|
end;
|
|
|
|
{ TcxSSFormatDialog }
|
|
|
|
{$IFDEF DELPHI9}
|
|
constructor TcxSSFormatDialog.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
Position := poDesigned;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
function TcxSSFormatDialog.Execute(const ACells: TRect; ASheet: TcxSSBookSheet): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
{ TcxWorkBookSubControl }
|
|
constructor TcxWorkBookSubControl.Create(AOwner: TcxCustomSpreadSheetBook);
|
|
begin
|
|
FOwner := AOwner;
|
|
FVisible := True;
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.Invalidate;
|
|
begin
|
|
Owner.InvalidateRect(BoundsRect, False);
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.InvalidateRect(ARect: TRect);
|
|
begin
|
|
if not Visible or Owner.Listener.IsLocked or not Owner.HandleAllocated then Exit;
|
|
OffsetRect(ARect, Left, Top);
|
|
if IntersectRect(ARect, BoundsRect, ARect) then;
|
|
Owner.InvalidateRect(ARect, False);
|
|
end;
|
|
|
|
function TcxWorkBookSubControl.ClientToScreen(const X, Y: Integer): TPoint;
|
|
begin
|
|
Result := Point(X + FBounds.Left, Y + FBounds.Top);
|
|
Result := Owner.ClientToScreen(Result)
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.DblClick;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.FocusChanged;
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.KeyDown(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.KeyPress(var Key: Char);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.KeyUp(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.Paint;
|
|
begin
|
|
if Visible then
|
|
Canvas.ExcludeClipRect(BoundsRect);
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.Resize;
|
|
begin
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.SetBounds(const ALeft, ATop, AWidth, AHeight: Integer);
|
|
begin
|
|
if EqualRect(FBounds, Rect(ALeft, ATop, AWidth, AHeight)) then Exit;
|
|
FBounds := Rect(ALeft, ATop, AWidth, AHeight);
|
|
Resize;
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.VisibleChanging;
|
|
begin
|
|
end;
|
|
|
|
function TcxWorkBookSubControl.GetBoundsRect: TRect;
|
|
begin
|
|
Result := Rect(FBounds.Left, FBounds.Top,
|
|
FBounds.Left + FBounds.Right, FBounds.Top + FBounds.Bottom);
|
|
end;
|
|
|
|
function TcxWorkBookSubControl.GetCanvas: TcxCanvasWrapper;
|
|
begin
|
|
Result := Owner.Canvas;
|
|
end;
|
|
|
|
function TcxWorkBookSubControl.GetClientRect: TRect;
|
|
begin
|
|
Result := Rect(0, 0, FBounds.Right, FBounds.Bottom);
|
|
end;
|
|
|
|
function TcxWorkBookSubControl.GetControlCanvas: TCanvas;
|
|
begin
|
|
Result := TCustomControlAccess(Owner).Canvas;
|
|
end;
|
|
|
|
function TcxWorkBookSubControl.GetCursor: TCursor;
|
|
begin
|
|
Result := Owner.Cursor;
|
|
end;
|
|
|
|
function TcxWorkBookSubControl.GetHeight: Integer;
|
|
begin
|
|
Result := FBounds.Bottom;
|
|
end;
|
|
|
|
function TcxWorkBookSubControl.GetLeft: Integer;
|
|
begin
|
|
Result := FBounds.Left;
|
|
end;
|
|
|
|
function TcxWorkBookSubControl.GetTop: Integer;
|
|
begin
|
|
Result := FBounds.Top;
|
|
end;
|
|
|
|
function TcxWorkBookSubControl.GetWidth: Integer;
|
|
begin
|
|
Result := FBounds.Right;
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.SetBoundsRect(ARect: TRect);
|
|
begin
|
|
ARect.Bottom := ARect.Bottom - ARect.Top;
|
|
ARect.Right := ARect.Right - ARect.Left;
|
|
if not EqualRect(ARect, FBounds) then
|
|
begin
|
|
FBounds := ARect;
|
|
Resize;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.SetCursor(const Value: TCursor);
|
|
begin
|
|
Owner.Cursor := Value;
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.SetHeight(const Value: Integer);
|
|
begin
|
|
if FBounds.Bottom = Value then Exit;
|
|
FBounds.Bottom := Value;
|
|
Resize;
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.SetLeft(const Value: Integer);
|
|
begin
|
|
FBounds.Left := Value;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.SetTop(const Value: Integer);
|
|
begin
|
|
FBounds.Top := Value;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.SetVisible(const Value: Boolean);
|
|
begin
|
|
if Value <> FVisible then
|
|
begin
|
|
if Value then
|
|
Invalidate;
|
|
FVisible := Value;
|
|
VisibleChanging;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxWorkBookSubControl.SetWidth(const Value: Integer);
|
|
begin
|
|
FBounds.Right := Value;
|
|
Resize;
|
|
end;
|
|
|
|
{ TcxSSCellObject }
|
|
constructor TcxSSCellObject.Create(AOwner: TcxSSDataStorage; ACol, ARow: Integer);
|
|
begin
|
|
FOwner := AOwner;
|
|
FCol := ACol;
|
|
FRow := ARow;
|
|
FComplexAction := nil;
|
|
with TcxHistoryAccess((FOwner.ParentBook as TcxCustomSpreadSheetBook).History) do
|
|
AddComplexAction(TcxComplexAction, cxGetResourceString(@scxChangeCellsData), FComplexAction)
|
|
end;
|
|
|
|
destructor TcxSSCellObject.Destroy;
|
|
begin
|
|
if FComplexAction <> nil then
|
|
TcxHistoryAccess((FOwner.ParentBook as TcxCustomSpreadSheetBook).History).StopComplexAction;
|
|
if Assigned(FCreatedStyle) then FCreatedStyle.Free;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxSSCellObject.Assign(Source: TcxSSCellObject);
|
|
begin
|
|
if Source <> nil then
|
|
begin
|
|
Style.ReadOnly := False;
|
|
Text := Source.Text;
|
|
Style.Assign(Source.Style);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSCellObject.SetCellText(const AText: string;
|
|
const NeedParse: Boolean = False);
|
|
var
|
|
ARec: TcxSSCellRec;
|
|
begin
|
|
if NeedParse then
|
|
Text := AText
|
|
else
|
|
begin
|
|
ARec := FOwner[FCol, FRow];
|
|
if ARec.DataType = dtFunction then
|
|
(FOwner.ParentBook as TcxCustomSpreadSheetBook).FormulasCache.DestroyFunction(ARec.FuncRecPtr);
|
|
ARec.DataType := dtText;
|
|
ARec.Text := AText;
|
|
FOwner[FCol, FRow] := ARec;
|
|
CheckCellWordBreak;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSCellObject.CheckCellWordBreak;
|
|
begin
|
|
OwnerSheet.ApplyAutoHeight(FRow);
|
|
end;
|
|
|
|
function TcxSSCellObject.GetCellStyle: IcxSpreadSheetCellStyle;
|
|
begin
|
|
Supports(TObject(Style), IcxSpreadSheetCellStyle, Result);
|
|
end;
|
|
|
|
function TcxSSCellObject.GetCellTextValue: string;
|
|
var
|
|
ACell: TcxSSCellRec;
|
|
AColor: Word;
|
|
begin
|
|
ACell := Owner[FCol, FRow];
|
|
if (ACell.DataType = dtFunction) then
|
|
begin
|
|
Result :=
|
|
TcxCustomSpreadSheetBook(Owner.ParentBook).FormulasCache.FuncRecToDisplayText(ACell.FuncRecPtr, AColor);
|
|
end
|
|
else
|
|
if ACell.DataType = dtDateTime then
|
|
Result := FloatToStr(ACell.DateTime)
|
|
else
|
|
Result := ACell.Text;
|
|
end;
|
|
|
|
function TcxSSCellObject.GetCellValue: Variant;
|
|
|
|
function TextToValue(const AText: string): Variant;
|
|
var
|
|
AFloat: Double;
|
|
ABool: Boolean;
|
|
begin
|
|
if cxTryStrToFloat(AText, AFloat) then
|
|
Result := AFloat
|
|
else
|
|
if cxTryStrToBool(AText, ABool) then
|
|
Result := ABool
|
|
else
|
|
Result := AText;
|
|
end;
|
|
|
|
var
|
|
ACell: TcxSSCellRec;
|
|
begin
|
|
ACell := FOwner[FCol, FRow];
|
|
case ACell.DataType of
|
|
dtText:
|
|
Result := TextToValue(ACell.Text);
|
|
dtFunction:
|
|
Result := TcxCustomSpreadSheetBook(Owner.ParentBook).FormulasCache.GetFuncValue(ACell.FuncRecPtr);
|
|
dtDateTime:
|
|
Result := ACell.DateTime;
|
|
dtControl:
|
|
Result := Integer(ACell.Control);
|
|
end;
|
|
end;
|
|
|
|
function TcxSSCellObject.GetDataType: TcxSSDataType;
|
|
begin
|
|
Result := FOwner.CellDataType[FCol, FRow];
|
|
end;
|
|
|
|
function TcxSSCellObject.GetDateTime: TDateTime;
|
|
begin
|
|
Result := FOwner.CellDateTime[FCol, FRow];
|
|
end;
|
|
|
|
function TcxSSCellObject.GetDisplayText: string;
|
|
begin
|
|
Result := OrdinalToFormatStr(GetCellTextValue, Owner[FCol, FRow].StylePtr^.FormatIndex,
|
|
TcxCustomSpreadSheetBook(Owner.ParentBook).Precision);
|
|
end;
|
|
|
|
function TcxSSCellObject.GetDisplayTextAlignment: TcxDisplayTextAlignment;
|
|
var
|
|
C: Word;
|
|
S: string;
|
|
ACell: TcxSSCellRec;
|
|
AHorzAlign: TcxHorzTextAlign;
|
|
begin
|
|
ACell := Owner[FCol, FRow];
|
|
if ACell.DataType = dtFunction then
|
|
S := OwnerSheet.Owner.FormulasCache.FuncRecToDisplayText(ACell.FuncRecPtr, C, False)
|
|
else
|
|
S := ACell.Text;
|
|
with ACell.StylePtr^ do
|
|
begin
|
|
AHorzAlign := HorzAlign;
|
|
if AHorzAlign = haGeneral then
|
|
begin
|
|
if FormatIndex <> 31 then
|
|
begin
|
|
if cxTryStrToFloat(S) then
|
|
Result := dtaRight
|
|
else
|
|
if cxTryStrToBool(S) then
|
|
Result := dtaCenter
|
|
else
|
|
Result := dtaLeft;
|
|
end
|
|
else
|
|
Result := dtaLeft;
|
|
end
|
|
else
|
|
Result := TcxDisplayTextAlignment(Byte(AHorzAlign) - 1);
|
|
end;
|
|
end;
|
|
|
|
function TcxSSCellObject.GetIsLoading: Boolean;
|
|
begin
|
|
Result := OwnerSheet.Owner.FormulasCache.IsLoading;
|
|
end;
|
|
|
|
function TcxSSCellObject.GetMergedRect: TRect;
|
|
begin
|
|
TcxSSDataStorage(FOwner).CheckInMergeRange(Point(FCol, FRow), Result);
|
|
end;
|
|
|
|
function TcxSSCellObject.GetOwnerSheet: TcxSSBookSheet;
|
|
begin
|
|
Result := TcxSSBookSheet(Owner.Owner);
|
|
end;
|
|
|
|
function TcxSSCellObject.GetText: string;
|
|
begin
|
|
Result := FOwner.CellText[FCol, FRow];
|
|
end;
|
|
|
|
function TcxSSCellObject.GetStyle: TcxSSCellStyle;
|
|
begin
|
|
if not Assigned(FCreatedStyle) then
|
|
FCreatedStyle := TcxSSCellStyle.Create(
|
|
TcxCustomSpreadSheetBook(Owner.ParentBook).StyleCache, Owner, FCol, FRow);
|
|
Result := FCreatedStyle;
|
|
end;
|
|
|
|
function TcxSSCellObject.GetStyleExist: Boolean;
|
|
begin
|
|
Result := (FCreatedStyle <> nil) or
|
|
(FOwner[FCol, FRow].StylePtr <> TcxCustomSpreadSheetBook(Owner.ParentBook).StyleCache.StyleList[0]);
|
|
end;
|
|
|
|
procedure TcxSSCellObject.SetStyle(const Value: TcxSSCellStyle);
|
|
begin
|
|
if Assigned(FCreatedStyle) and (FCreatedStyle <> Value) then
|
|
FCreatedStyle.Assign(Value)
|
|
else
|
|
GetStyle.Assign(Value);
|
|
end;
|
|
|
|
procedure TcxSSCellObject.SetDateTime(const Value: TDateTime);
|
|
begin
|
|
FOwner.CellDateTime[FCol, FRow] := Value;
|
|
if Style.Format = 0 then
|
|
begin
|
|
if Trunc(Value) = 0 then
|
|
Style.Format := $15
|
|
else
|
|
begin
|
|
if Frac(Value) = 0 then
|
|
Style.Format := $0E
|
|
else
|
|
Style.Format := $16;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSCellObject.SetText(const Value: string);
|
|
begin
|
|
if CellReadOnly(OwnerSheet.Owner, OwnerSheet, Col, Row) then Exit;
|
|
SetTextEx(Value);
|
|
end;
|
|
|
|
procedure TcxSSCellObject.SetTextEx(const Value: string;
|
|
IsFormula: Boolean = False; Analyze: Boolean = True);
|
|
var
|
|
DT: TDateTime;
|
|
C: Currency;
|
|
begin
|
|
if CellReadOnly(OwnerSheet.Owner, OwnerSheet, Col, Row) then Exit;
|
|
if ((Style.Format = 0) or FormatIsDateTime(TcxStyleAccess(Style).StyleInfo.FormatIndex))
|
|
and cxTryStrToDateTime(Value, DT) and not cxTryStrToFloat(Value) then
|
|
SetDateTime(DT)
|
|
else
|
|
if ((Style.Format = 0) or FormatIsCurrency(TcxStyleAccess(Style).StyleInfo.FormatIndex)) and
|
|
cxTryStrToCurr(Value, C) and not cxTryStrToFloat(Value) then
|
|
begin
|
|
FOwner.CellText[FCol, FRow] := FloatToStr(C);
|
|
if Style.Format = 0 then
|
|
Style.Format := $8;
|
|
end
|
|
else
|
|
TcxDataStorageAccess(FOwner).SetCellTextEx(FCol, FRow, Value, IsFormula, Analyze);
|
|
CheckCellWordBreak;
|
|
TcxCustomSpreadSheetBook(Owner.ParentBook).UpdateControl;
|
|
end;
|
|
|
|
{ TcxSSClipboard }
|
|
function TcxSSClipboard.GetESSData: AnsiString;
|
|
begin
|
|
SetLength(Result, BufferSize(CF_ESSDATA));
|
|
if Length(Result) > 0 then
|
|
GetBuffer(CF_ESSDATA, Result[1]);
|
|
end;
|
|
|
|
function TcxSSClipboard.GetUnicodeData: WideString;
|
|
begin
|
|
if BufferSize(CF_UNICODETEXT) <> 0 then
|
|
begin
|
|
SetLength(Result, BufferSize(CF_UNICODETEXT) shr 1 - 1);
|
|
GetBuffer(CF_UNICODETEXT, Result[1]);
|
|
end
|
|
else
|
|
Result := ClipBoard.AsText;
|
|
if (Result <> '') then
|
|
begin
|
|
case Result[Length(Result)] of
|
|
#13, #10:;
|
|
else
|
|
Result := Result + #13#10;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSClipboard.SetESSData(const Value: AnsiString);
|
|
begin
|
|
if Value <> '' then
|
|
begin
|
|
SetBuffer(CF_ESSDATA, Value[1], Length(Value) + 1, True);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSClipboard.SetUnicodeData(const Value: WideString);
|
|
begin
|
|
if Value <> '' then
|
|
begin
|
|
SetBuffer(CF_UNICODETEXT, Value[1], (Length(Value) + 1) shl 1, False);
|
|
end;
|
|
end;
|
|
|
|
function TcxSSClipboard.BufferSize(AFormat: Word): Integer;
|
|
var
|
|
AData: THandle;
|
|
ADataPtr: Pointer;
|
|
begin
|
|
Result := 0;
|
|
if not OpenClipboard(Application.Handle) then Exit;
|
|
try
|
|
AData := GetClipboardData(AFormat);
|
|
if AData = 0 then Exit;
|
|
ADataPtr := GlobalLock(AData);
|
|
if ADataPtr = nil then Exit;
|
|
try
|
|
Result := GlobalSize(AData);
|
|
finally
|
|
GlobalUnlock(AData);
|
|
end;
|
|
finally
|
|
CloseClipboard;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSClipboard.GetBuffer(AFormat: Word; var ABuffer);
|
|
var
|
|
Data: THandle;
|
|
DataPtr: Pointer;
|
|
begin
|
|
if not OpenClipboard(Application.Handle) then Exit;
|
|
try
|
|
Data := GetClipboardData(AFormat);
|
|
if Data = 0 then Exit;
|
|
DataPtr := GlobalLock(Data);
|
|
if DataPtr = nil then Exit;
|
|
try
|
|
Move(DataPtr^, ABuffer, GlobalSize(Data));
|
|
finally
|
|
GlobalUnlock(Data);
|
|
end;
|
|
finally
|
|
CloseClipboard;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSClipboard.SetBuffer(AFormat: Word; const ABuffer; ASize: Integer;
|
|
ClearClipboard: Boolean);
|
|
var
|
|
Data: THandle;
|
|
DataPtr: Pointer;
|
|
begin
|
|
if not OpenClipboard(Application.Handle) then Exit;
|
|
try
|
|
if ClearClipBoard then
|
|
EmptyClipboard;
|
|
if ASize > 0 then
|
|
begin
|
|
Data := GlobalAlloc(GMEM_MOVEABLE + GMEM_DDESHARE, ASize);
|
|
try
|
|
DataPtr := GlobalLock(Data);
|
|
try
|
|
Move(ABuffer, DataPtr^, ASize);
|
|
SetClipboardData(AFormat, Data);
|
|
finally
|
|
GlobalUnlock(Data);
|
|
end;
|
|
except
|
|
GlobalFree(Data);
|
|
raise;
|
|
end;
|
|
end;
|
|
finally
|
|
CloseClipBoard;
|
|
end;
|
|
end;
|
|
|
|
{ procedure SaveBiffToFile;
|
|
var
|
|
Data: Integer;
|
|
DataPtr: Pointer;
|
|
AFormat, I: Integer;
|
|
Name: array[0..255] of Char;
|
|
F: File;
|
|
begin
|
|
OpenClipboard(0);
|
|
try
|
|
for I := 0 to CountClipboardFormats - 1 do
|
|
begin
|
|
AFormat := EnumClipBoardFormats(I);
|
|
GetClipBoardFormatName(AFormat, Name, Sizeof(Name));
|
|
if Name = 'Biff8' then
|
|
begin
|
|
Data := GetClipboardData(AFormat);
|
|
if Data = 0 then Exit;
|
|
DataPtr := GlobalLock(Data);
|
|
if DataPtr = nil then Exit;
|
|
try
|
|
AssignFile(F, 'C:\BinaryClipboard.xls');
|
|
Rewrite(F, 1);
|
|
BlockWrite(F, DataPtr^, GlobalSize(Data));
|
|
CloseFile(F);
|
|
finally
|
|
GlobalUnlock(Data);
|
|
end;
|
|
end;
|
|
end;
|
|
finally
|
|
CloseClipboard;
|
|
end;
|
|
end;}
|
|
|
|
{ TcxCustomSpreadSheetBook }
|
|
constructor TcxCustomSpreadSheetBook.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FFloatPrecision := 2;
|
|
FListener := GetListenerClass.Create(Self);
|
|
FRowsAutoHeight := True;
|
|
FHistory := GetHistoryClass.Create;
|
|
FExcelProtectionStyle := True;
|
|
TcxHistoryAccess(FHistory).HistoryOwner := Self;
|
|
TcxHistoryAccess(FHistory).OnChange := FListener.OnHistoryChanged;
|
|
TcxHistoryAccess(FHistory).BeginUpdate;
|
|
FPaintBitmap := nil;
|
|
FBufferedPaint := False;
|
|
FPalette := cxExcelStdColors;
|
|
FHeaderFont := TFont.Create;
|
|
FCanvas := TcxCanvasWrapper.Create(@FPalette);
|
|
FHeaderFont.OnChange := OnChangeHeaderStyle;
|
|
FCaptionBar := GetBookPageCaptionsClass.Create(Self);
|
|
FPages := TList.Create;
|
|
FCaptionBar.Visible := True;
|
|
FShowCaptionBar := True;
|
|
FShowGrid := True;
|
|
FDefaultColWidth := 85;
|
|
FDefaultRowHeight := 20;
|
|
FColHeaderHeight := 20;
|
|
FRowHeaderWidth := 85;
|
|
FPainterType := ptOffice97Style;
|
|
FPainter := GetPainterClass.Create;
|
|
FStyleCache := GetStyleCacheClass.Create(Self);
|
|
FFormulasCache := GetFormulasCacheClass.Create(Self);
|
|
FReadOnly := False;
|
|
Keys := [kAll, kArrows, kChars, kTab];
|
|
HScrollBar.Visible := True;
|
|
VScrollBar.Visible := True;
|
|
SetDefaultColor(clWindow);
|
|
SetGridColor(clBtnFace);
|
|
SetHeaderColor(clBtnFace);
|
|
ScrollBars := sbsBoth;
|
|
SetSelectionColor(clHighLight);
|
|
SetBounds(Left, Top, 350, 200);
|
|
TcxHistoryAccess(FHistory).EndUpdate;
|
|
{$IFNDEF cxLib10}
|
|
LookAndFeel.Kind := lfFlat;
|
|
{$ENDIF}
|
|
FTimer := TTimer.Create(Self);
|
|
FTimer.Interval := 10;
|
|
FTimer.Enabled := False;
|
|
FTimer.OnTimer := OnMouseTimerHandle;
|
|
end;
|
|
|
|
destructor TcxCustomSpreadSheetBook.Destroy;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FTimer.Enabled := False;
|
|
FTimer.Free;
|
|
FListener.BeginUpdate;
|
|
if Assigned(FPaintBitmap) then
|
|
FPaintBitmap.Free;
|
|
for I := 0 to PageCount - 1 do
|
|
Pages[I]._Release;
|
|
FCellEditor.Free;
|
|
FHistory.Free;
|
|
FCaptionBar.Free;
|
|
FCanvas.Free;
|
|
FPainter.Free;
|
|
FHeaderFont.Free;
|
|
FPages.Free;
|
|
FStyleCache.Free;
|
|
FFormulasCache.Free;
|
|
FListener.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.Assign(Source: TPersistent);
|
|
var
|
|
I: Integer;
|
|
ASourceBook: TcxCustomSpreadSheetBook;
|
|
begin
|
|
if (Source is TcxCustomSpreadSheetBook) and (Source <> Self) then
|
|
begin
|
|
ASourceBook := TcxCustomSpreadSheetBook(Source);
|
|
Listener.BeginUpdate;
|
|
try
|
|
ClearAll;
|
|
DefaultStyle.Assign(ASourceBook.DefaultStyle);
|
|
FPalette := ASourceBook.FPalette;
|
|
for I := 0 to ASourceBook.PageCount - 1 do
|
|
begin
|
|
AddSheetPage;
|
|
Pages[I].Assign(ASourceBook[I]);
|
|
end;
|
|
finally
|
|
Listener.EndUpdate;
|
|
CaptionBar.FirstVisibleCaption := ASourceBook.CaptionBar.FirstVisibleCaption;
|
|
FActivePage := -1;
|
|
ActivePage := ASourceBook.ActivePage;
|
|
CaptionBar.RecalcViewInfo;
|
|
FReadOnly := ASourceBook.FReadOnly;
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.BeginUpdate: Integer;
|
|
begin
|
|
Result := FListener.BeginUpdate;
|
|
if FFormulasCache <> nil then
|
|
FFormulasCache.Lock := True;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.CellsNameByRef(ASheet: Integer;
|
|
const CellsRef: TRect; IsText: Boolean = True): string;
|
|
|
|
function CellRefToText(const APoint: TPoint): string;
|
|
begin
|
|
if R1C1ReferenceStyle then
|
|
Result := 'R' + IntToStr(APoint.Y + 1) + 'C' + IntToStr(APoint.X + 1) + ''
|
|
else
|
|
Result := TcxSSUtils.ColumnNameByIndex(APoint.X, R1C1ReferenceStyle) + IntToStr(APoint.Y + 1);
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
const
|
|
Separators: array[Boolean] of string = (':', ' x ');
|
|
begin
|
|
if IsText then
|
|
begin
|
|
for I := 0 to Length(DefinedNames) - 1 do
|
|
begin
|
|
with DefinedNames[I].Definition do
|
|
begin
|
|
if (Page = ASheet) and EqualRect(TRect(Area), CellsRef) and not DefinedNames[I].IsDeleted then
|
|
begin
|
|
Result := DefinedNames[I].Name;
|
|
Exit;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
Result := CellRefToText(CellsRef.TopLeft);
|
|
if Int64(CellsRef.TopLeft) <> Int64(CellsRef.BottomRight) then
|
|
Result := Result + Separators[IsText] + CellRefToText(CellsRef.BottomRight)
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.ClearAll;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to PageCount - 1 do
|
|
Pages[I]._Release;
|
|
FormulasCache.Clear;
|
|
FStyleCache.Clear;
|
|
FPages.Clear;
|
|
FActivePage := 0;
|
|
FHistory.Clear;
|
|
if HandleAllocated and not Listener.IsLocked then
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.DeactivateEditor;
|
|
begin
|
|
if Assigned(FCellEditor) and FCellEditor.Visible then
|
|
begin
|
|
FCellEditor.Visible := False;
|
|
SetFocus;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.DeleteName(const AName: string): Boolean;
|
|
begin
|
|
Result := FFormulasCache.DeleteName(AName);
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.DefineName(const AName: string;
|
|
APage: Word; const ARect: TRect): Integer;
|
|
begin
|
|
Result := FFormulasCache.DefineName(AName, APage, TRange(ARect));
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.DefineNameEx(const AName: string;
|
|
APage: Word; const ARect: TRect; Validate: Boolean = True): Integer;
|
|
begin
|
|
Result := FFormulasCache.DefineName(AName, APage, TRange(ARect), Validate);
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.EndUpdate: Integer;
|
|
begin
|
|
FFormulasCache.Lock := False;
|
|
Result := FListener.EndUpdate;
|
|
if Assigned(FCaptionBar) then
|
|
begin
|
|
FCaptionBar.ReCalcViewInfo;
|
|
FCaptionBar.Invalidate;
|
|
end;
|
|
if Result <= 0 then
|
|
UpdateControl;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.HasRectName(ASheet: Integer; const ARect: TRect): Integer;
|
|
var
|
|
I: Integer;
|
|
ANames: TcxSSNamesDef;
|
|
begin
|
|
ANames := DefinedNames;
|
|
Result := -1;
|
|
for I := 0 to Length(ANames) - 1 do
|
|
with ANames[I].Definition do
|
|
if (Page = ASheet) and EqualRect(TRect(Area), ARect) and not ANames[I].IsDeleted then
|
|
begin
|
|
Result := I;
|
|
Break;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.HitTest(const APoint: TPoint; out HitTestInfo: TcxSSHitTestInfo): Boolean;
|
|
var
|
|
I: Integer;
|
|
ACol, ARow: Integer;
|
|
AStates: TcxSSHitTestStates;
|
|
begin
|
|
FillChar(HitTestInfo, SizeOf(HitTestInfo), 0);
|
|
Result := False;
|
|
if FCaptionBar.Visible and PtInRect(FCaptionBar.BoundsRect, APoint) then
|
|
begin
|
|
case FCaptionBar.HitTest(APoint.X, APoint.Y - FCaptionBar.Top, I) of
|
|
htCaption:
|
|
begin
|
|
HitTestInfo.HitType := htSheetCaption;
|
|
HitTestInfo.Page := I;
|
|
Result := True;
|
|
end;
|
|
htButton:
|
|
begin
|
|
HitTestInfo.HitType := htCaptionButton;
|
|
HitTestInfo.Button := TcxSSNavigatorBtn(I);
|
|
Result := True;
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
if (PageCount > 0) and PtInRect(ActiveSheet.BoundsRect, APoint) then
|
|
begin
|
|
Result := True;
|
|
AStates := ActiveSheet.ViewInfo.HitTest(APoint.X, APoint.Y, ACol, ARow);
|
|
if htCell in AStates then
|
|
begin
|
|
HitTestInfo.HitType := htSheetCell;
|
|
HitTestInfo.CellCol := ACol;
|
|
HitTestInfo.CellRow := ARow;
|
|
end
|
|
else
|
|
if htRowHeader in AStates then
|
|
begin
|
|
HitTestInfo.HitType := htSheetRow;
|
|
HitTestInfo.Row := ARow;
|
|
end
|
|
else
|
|
if htColHeader in AStates then
|
|
begin
|
|
HitTestInfo.HitType := htSheetColumn;
|
|
HitTestInfo.Col := ACol;
|
|
end
|
|
else
|
|
if htUpperLeft in AStates then
|
|
begin
|
|
HitTestInfo.HitType := htSheetColumn;
|
|
HitTestInfo.CellCol := -1;
|
|
HitTestInfo.CellRow := -1;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.LoadFromFile(const AFileName: string);
|
|
var
|
|
AFileStream: TFileStream;
|
|
begin
|
|
if FileExists(AFileName) then
|
|
begin
|
|
AFileStream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone);
|
|
try
|
|
LoadFromStream(AFileStream);
|
|
finally
|
|
AFileStream.Free;
|
|
end;
|
|
end
|
|
else
|
|
raise ESpreadSheetError.CreateFmt(cxGetResourceString(@scxSpreadSheetInvalidFileName), [AFileName]);
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.LoadFromStream(Stream: TStream);
|
|
var
|
|
AReader: TcxExcelFileReader;
|
|
ACursor: TCursor;
|
|
I, J: Integer;
|
|
ALockRef: Integer;
|
|
begin
|
|
ALockRef := TcxFormulasAccess(FFormulasCache).FLockRef;
|
|
AReader := TcxExcelFileReader.Create(Self);
|
|
ReadOnly := False;
|
|
History.Clear;
|
|
History.BeginUpdate;
|
|
BeginUpdate;
|
|
ACursor := Screen.Cursor;
|
|
Screen.Cursor := crHourGlass;
|
|
R1C1ReferenceStyle := False;
|
|
IsDataLoading := True;
|
|
if FCaptionBar.Visible then
|
|
FCaptionBar.FirstVisibleCaption := 0;
|
|
try
|
|
FIsLoaded := True;
|
|
if AReader.AssignStream(Stream) then
|
|
begin
|
|
try
|
|
ClearAll;
|
|
FFormulasCache.IsLoading := True;
|
|
FFormulasCache.Lock := True;
|
|
FPalette := cxExcelStdColors;
|
|
AReader.OnProgress := Listener.OnProgress;
|
|
AReader.OpenStream;
|
|
FModified := False;
|
|
except
|
|
try
|
|
ClearAll;
|
|
if PageCount <> 0 then
|
|
Pages[0].Caption := cxGetResourceString(@scxSheetName) + IntToStr(1)
|
|
else
|
|
AddSheetPage;
|
|
finally
|
|
raise EdxException.Create(cxGetResourceString(@scxSpreadSheetInvalidStreamFormat));
|
|
end;
|
|
end
|
|
end
|
|
else
|
|
raise ESpreadSheetError.Create(cxGetResourceString(@scxSpreadSheetInvalidStreamFormat));
|
|
if AReader.HasUnknownFunction then
|
|
raise ESpreadSheetError.Create(cxGetResourceString(@scxXLSFileHasUnknownFunction));
|
|
finally
|
|
IsDataLoading := False;
|
|
if RowsAutoHeight then
|
|
begin
|
|
for I := 0 to PageCount - 1 do
|
|
for J := 0 to Pages[I].RowCount - 1 do
|
|
Pages[I].ApplyAutoHeight(J);
|
|
end;
|
|
FActivePage := -1;
|
|
ActivePage := 0;
|
|
FIsLoaded := False;
|
|
FFormulasCache.IsLoading := False;
|
|
Screen.Cursor := ACursor;
|
|
EndUpdate;
|
|
AReader.Free;
|
|
AdjustControls;
|
|
UpdateControl;
|
|
History.EndUpdate;
|
|
History.Clear;
|
|
TcxFormulasAccess(FFormulasCache).FLockRef := ALockRef;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.Recalc;
|
|
begin
|
|
if Listener.IsLocked then Exit;
|
|
FFormulasCache.Updating := True;
|
|
try
|
|
if PageCount > 0 then FFormulasCache.Recalc;
|
|
finally
|
|
FFormulasCache.Updating := False;
|
|
if (FFormulasCache.FuncCount > 0)then
|
|
try
|
|
if Assigned(OnAfterCalculation) then
|
|
begin
|
|
Listener.BeginUpdate;
|
|
OnAfterCalculation(Self);
|
|
Listener.EndUpdate;
|
|
end;
|
|
finally
|
|
InternalUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SaveToFile(const AFileName: string);
|
|
var
|
|
AStream: TFileStream;
|
|
begin
|
|
AStream := TFileStream.Create(AFileName, fmOpenWrite or fmCreate or fmShareDenyNone);
|
|
try
|
|
SaveToStream(AStream);
|
|
finally
|
|
AStream.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SaveToStream(AStream: TStream);
|
|
var
|
|
I, J: Integer;
|
|
ACursor: TCursor;
|
|
APage: Integer;
|
|
AWriter: TcxExcelFileWriter;
|
|
|
|
procedure SetColsRowsInformation;
|
|
var
|
|
J: Integer;
|
|
AHeader: TcxHeaderAccess;
|
|
begin
|
|
AHeader := TcxHeaderAccess(Pages[APage].Cols);
|
|
AWriter.SetDefaultColWidth(APage, AHeader.DefaultSize);
|
|
for J := 0 to AHeader.Count - 1 do
|
|
if J < 255 then
|
|
with AHeader.Data^[J] do
|
|
if (hsHidden in States) or (not (hsDefault in States)) or not (hsLockProtect in States) then
|
|
AWriter.SetColStyle(APage, J, Size, (hsLockProtect in States) <> DefaultStyle.Locked, hsHidden in States);
|
|
AHeader := TcxHeaderAccess(Pages[APage].Rows);
|
|
AWriter.SetDefaultRowHeight(APage, AHeader.DefaultSize);
|
|
for J := 0 to AHeader.Count - 1 do
|
|
begin
|
|
if J < $FFFF then
|
|
with AHeader.Data^[J] do
|
|
if (hsHidden in States) or (not (hsDefault in States)) then
|
|
AWriter.SetRowStyle(APage, J, Size, hsHidden in States);
|
|
end;
|
|
end;
|
|
|
|
procedure SetCellValue(ACol, ARow: Word; ACell: PcxSSCellRec; AllowFormula: Boolean = False);
|
|
var
|
|
AStackItem: TcxStackItem;
|
|
begin
|
|
if (ACell <> nil) and (AllowFormula = (ACell^.DataType = dtFunction)) then
|
|
begin
|
|
AWriter.SelectStyle(ACell.StylePtr);
|
|
case ACell^.DataType of
|
|
dtText:
|
|
AWriter.SetCellValue(APage, ACol, ARow, ACell^.Text, ACell^.StylePtr^.FormatIndex = $31);
|
|
dtDateTime:
|
|
AWriter.SetCellValue(APage, ACol, ARow, ACell^.DateTime);
|
|
dtFunction:
|
|
try
|
|
AStackItem :=
|
|
FFormulasCache.SpreadSheetTokensToExcelTokens(ACell^.FuncRecPtr);
|
|
if AStackItem.Size > 0 then
|
|
AWriter.SetCellFunction(APage, ACol, ARow,
|
|
ACell^.FuncRecPtr^.CalcResult, AStackItem.Size, AStackItem.Tokens);
|
|
finally
|
|
FreeMem(AStackItem.Tokens);
|
|
FillChar(AStackItem, SizeOf(TcxStackItem), 0);
|
|
AStackItem.Tokens := nil;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
AWriter := TcxExcelFileWriter.Create(Self);
|
|
ACursor := Screen.Cursor;
|
|
Screen.Cursor := crHourGlass;
|
|
Listener.OnProgress(Self, 0);
|
|
TcxHistoryAccess(History).Clear;
|
|
TcxHistoryAccess(History).BeginUpdate;
|
|
try
|
|
AWriter.PageCount := PageCount;
|
|
AWriter.SetPalette(@FPalette);
|
|
AWriter.SetProtection(-1, Protected);
|
|
for I := 0 to Length(DefinedNames) - 1 do
|
|
AWriter.DefineName(@DefinedNames[I]);
|
|
AWriter.SetDefaultStyle(TcxStyleAccess(StyleCache.DefaultStyle).StylePtr);
|
|
for APage := 0 to PageCount - 1 do
|
|
begin
|
|
Listener.OnProgress(Self, MulDiv(APage, 100, PageCount));
|
|
AWriter.AddSheet(Pages[APage].Caption, Pages[APage].ShowGrid, True);
|
|
AWriter.SetProtection(APage, Pages[APage].Protected);
|
|
with TcxDataStorageAccess(Pages[APage].DataStorage) do
|
|
begin
|
|
SetColsRowsInformation;
|
|
for I := 0 to MaxColumn - 1 do
|
|
for J := 0 to Columns[I].CellsCount - 1 do
|
|
if (I <= 255) and (J <= $FFFF) then
|
|
SetCellValue(I, J, Columns[I].Cells^[J]);
|
|
for I := 0 to MaxColumn - 1 do
|
|
for J := 0 to Columns[I].CellsCount - 1 do
|
|
if (I <= 255) and (J <= $FFFF) then
|
|
SetCellValue(I, J, Columns[I].Cells^[J], True);
|
|
AWriter.SetMergedCells(APage, MergedCells.Rects);
|
|
end;
|
|
end;
|
|
AWriter.SaveToStream(AStream);
|
|
finally
|
|
Screen.Cursor := ACursor;
|
|
TcxHistoryAccess(History).EndUpdate;
|
|
AWriter.Free;
|
|
Listener.OnProgress(Self, 100);
|
|
end;
|
|
FModified := False;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.UpdateControl;
|
|
begin
|
|
if not Listener.IsLocked then
|
|
begin
|
|
DoRecalc;
|
|
InternalUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.AddPage(ASheet: TcxSSBookSheet);
|
|
var
|
|
APageId: Integer;
|
|
begin
|
|
APageId := FPages.Add(ASheet);
|
|
if APageId = 0 then
|
|
begin
|
|
FActivePage := 0;
|
|
ASheet.Visible := True;
|
|
end
|
|
else
|
|
ASheet.Visible := False;
|
|
SetLength(FPageVisible, APageId + 1);
|
|
PageVisible[APageId] := True;
|
|
if HandleAllocated then
|
|
begin
|
|
FCaptionBar.ReCalcViewInfo;
|
|
FCaptionBar.Invalidate;
|
|
end;
|
|
if (APageID = 0) or (APageID = ActivePage) then
|
|
AdjustControls;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.AddSheetPage(const APageName: string = '');
|
|
var
|
|
ASheetPage: TcxSSBookSheet;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
ASheetPage := GetSheetClass.Create(Self);
|
|
ASheetPage._AddRef;
|
|
if APageName = '' then
|
|
ASheetPage.DataStorage.SheetCaption := cxGetResourceString(@scxSheetName) + IntToStr(PageCount + 1)
|
|
else
|
|
ASheetPage.DataStorage.SheetCaption := APageName;
|
|
AddPage(ASheetPage);
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.AdjustControls;
|
|
var
|
|
AVScrollWidth: Integer;
|
|
AHScrollHeight: Integer;
|
|
AHeight: Integer;
|
|
AWidth: Integer;
|
|
begin
|
|
if FCaptionBar = nil then Exit;
|
|
if FCaptionBar.Visible then
|
|
FCaptionBar.RecalcViewInfo;
|
|
if ScrollersVisible[FScrollBars, sbVertical] then
|
|
AVScrollWidth := VScrollBar.Width
|
|
else
|
|
AVScrollWidth := 0;
|
|
if FCaptionBar.Visible or ScrollersVisible[FScrollBars, sbHorizontal] then
|
|
AHScrollHeight := FCaptionBar.Height
|
|
else
|
|
AHScrollHeight := 0;
|
|
if HandleAllocated then
|
|
begin
|
|
AHeight := ClientHeight;
|
|
AWidth := ClientWidth;
|
|
end
|
|
else
|
|
begin
|
|
AHeight := Height;
|
|
AWidth := Width;
|
|
end;
|
|
if FCaptionBar.Visible then
|
|
FCaptionBar.SetBounds(0, AHeight - AHScrollHeight, Width, AHScrollHeight);
|
|
if PageCount > 0 then
|
|
ActiveSheet.SetBounds(0, 0, AWidth - AVScrollWidth,
|
|
AHeight - AHScrollHeight);
|
|
UpdateControl;
|
|
FCaptionBar.ReCalcViewInfo;
|
|
FCaptionBar.Invalidate;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.DblClick;
|
|
begin
|
|
inherited;
|
|
if PageCount > 0 then
|
|
begin
|
|
with FMouseDownPos do
|
|
begin
|
|
if FCaptionBar.Visible and PtInRect(FCaptionBar.BoundsRect, Point(X, Y)) then
|
|
FCaptionBar.DblClick
|
|
else
|
|
ActiveSheet.DblClick;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.DoRecalc;
|
|
begin
|
|
if AutoRecalc then Recalc;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.DoMouseWheel(Shift: TShiftState;
|
|
WheelDelta: Integer; MousePos: TPoint): Boolean;
|
|
begin
|
|
Result := inherited DoMouseWheel(Shift, WheelDelta, MousePos);
|
|
if (PageCount > 0) and ((FCaptureControl = nil) or
|
|
((FCaptureControl <> nil) and (FCaptureControl = ActiveSheet))) then
|
|
Result := ActiveSheet.DoMousewheel(Shift, WheelDelta, MousePos);
|
|
end;
|
|
|
|
{$IFDEF DELPHI5}
|
|
procedure TcxCustomSpreadSheetBook.DoContextPopup(
|
|
MousePos: TPoint; var Handled: Boolean);
|
|
begin
|
|
if not FContextPopupHandled then
|
|
begin
|
|
inherited;
|
|
FContextPopupHandled := False;
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
procedure TcxCustomSpreadSheetBook.FocusChanged;
|
|
begin
|
|
FCaptionBar.FocusChanged;
|
|
if PageCount > 0 then
|
|
ActiveSheet.FocusChanged;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetBookPageCaptionsClass: TcxSSBookPageCaptionsClass;
|
|
begin
|
|
Result := TcxSSBookPageCaptions;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetCaptionPainterClass: TcxPageCaptionPainterClass;
|
|
begin
|
|
Result := TcxPageCaptionPainter
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetDataStorageClass: TcxSSDataStorageClass;
|
|
begin
|
|
Result := TcxSSDataStorage;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetFormulasCacheClass: TcxFormulasCacheClass;
|
|
begin
|
|
Result := TcxSSFormulasCache;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetHeaderClass: TcxSSHeaderClass;
|
|
begin
|
|
Result := TcxSSHeader;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetHistoryClass: TcxSSHistoryClass;
|
|
begin
|
|
Result := TcxSpreadSheetHistory;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetHScrollBarBounds: TRect;
|
|
var
|
|
AClientSize: TSize;
|
|
HScrollHeight: Integer;
|
|
begin
|
|
if FCaptionBar.Visible then
|
|
HScrollHeight := FCaptionBar.Height
|
|
else
|
|
HScrollHeight := cxHScrollHeight;
|
|
AClientSize := TSize(ClientRect.BottomRight);
|
|
if ScrollersVisible[FScrollBars, sbHorizontal] then
|
|
with AClientSize do
|
|
begin
|
|
if ScrollersVisible[FScrollBars, sbVertical] then
|
|
Result := Rect(0, CY - HScrollHeight, CX - cxVScrollWidth, CY)
|
|
else
|
|
Result := Rect(0, CY - HScrollHeight, CX, CY);
|
|
if FCaptionBar.Visible then
|
|
Result.Left := CX shr 1
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetInplaceEditClass: TcxSSInplaceEditClass;
|
|
begin
|
|
Result := TcxSSInplaceTextEdit;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetListenerClass: TcxSSListenerClass;
|
|
begin
|
|
Result := TcxSSListener;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetPainterClass: TcxSheetPainterClass;
|
|
const
|
|
APainters: array[TcxSSPainterType] of TcxSheetPainterClass =
|
|
(TcxSheetPainter, TcxXPPainter, TcxSheetPainter);
|
|
begin
|
|
Result := APainters[FPainterType];
|
|
if (FPainterType = ptCustom) and not IsDesigning then
|
|
if Assigned(FOnCustomPaint) then
|
|
FOnCustomPaint(Self, Result);
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetPalettePtr: PcxExcelPalette;
|
|
begin
|
|
Result := @FPalette;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetStyleCacheClass: TcxSSStyleCacheClass;
|
|
begin
|
|
Result := TcxSSStyleCache;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetSheetClass: TcxSSBookSheetClass;
|
|
begin
|
|
Result := TcxSSBookSheet;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetVScrollBarBounds: TRect;
|
|
var
|
|
AClientSize: TSize;
|
|
begin
|
|
AClientSize := TSize(ClientRect.BottomRight);
|
|
if ScrollersVisible[FScrollBars, sbVertical] then
|
|
with AClientSize do
|
|
begin
|
|
if ScrollersVisible[FScrollBars, sbHorizontal] or FCaptionBar.Visible then
|
|
Result := Rect(CX - cxVScrollWidth, 0, CX, CY - HScrollbar.Height)
|
|
else
|
|
Result := Rect(CX - cxVScrollWidth, 0, CX, CY)
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetViewInfoClass: TcxSSheetViewInfoClass;
|
|
begin
|
|
Result := TcxSSheetViewInfo;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.Paint;
|
|
var
|
|
ARect: TRect;
|
|
|
|
procedure PaintControls;
|
|
var
|
|
AClipRgn, ARgn : TcxRegionHandle;
|
|
begin
|
|
if FCaptionBar.Visible then
|
|
begin
|
|
AClipRgn := CreateRectRgnIndirect(ClientRect);
|
|
ARgn := CreateRectRgnIndirect(FCaptionBar.BoundsRect);
|
|
GetClipRgn(Canvas.Handle, AClipRgn);
|
|
CombineRgn(ARgn, AClipRgn, ARgn, RGN_AND);
|
|
Canvas.ExcludeClipRect(FCaptionBar.BoundsRect);
|
|
end
|
|
else
|
|
begin
|
|
AClipRgn := EmptyHandle;
|
|
ARgn := EmptyHandle;
|
|
end;
|
|
if ActiveSheet.Visible then
|
|
ActiveSheet.Paint;
|
|
if FCaptionBar.Visible then
|
|
begin
|
|
SelectClipRgn(Canvas.Handle, ARgn);
|
|
DeleteObject(AClipRgn);
|
|
DeleteObject(ARgn);
|
|
if FCaptionBar.Visible and ScrollersVisible[FScrollBars, sbHorizontal] then
|
|
ARect := Rect(HScrollBar.Left, HScrollBar.Top,
|
|
Width + 1, Height + 1);
|
|
FCaptionBar.Paint;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
inherited Paint;
|
|
Painter.HideSelection := HideSelection and not Focused;
|
|
Canvas.BeginPaint(inherited Canvas.Canvas);
|
|
if PageCount > 0 then
|
|
begin
|
|
if BufferedPaint then
|
|
begin
|
|
Canvas.BeginPaint(FPaintBitmap.Canvas);
|
|
SelectClipRgn(FPaintBitmap.Canvas.Handle, 0);
|
|
if (FCaptionBar <> nil) and (FCaptionBar.Visible) then
|
|
FCaptionBar.Paint;
|
|
if ActiveSheet.ViewInfo.InfoChanged then
|
|
ActiveSheet.Paint;
|
|
BitBlt(inherited Canvas.Handle, 0, 0, Width,
|
|
Height, FPaintBitmap.Canvas.Handle, 0, 0, srcCopy);
|
|
end
|
|
else
|
|
PaintControls;
|
|
end
|
|
else
|
|
begin
|
|
ARect := Rect(0, 0, ClientWidth - 1, ClientHeight -1);
|
|
Canvas.FillRect(ARect, fsSolid, clBtnFace, cxSSDefaultColorValue);
|
|
Canvas.FrameRect(ARect, clBtnHighLight, clBtnShadow);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.InitScrollBarsParameters;
|
|
begin
|
|
if PageCount > 0 then
|
|
ActiveSheet.InitScrollBars;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.InternalUpdate;
|
|
begin
|
|
if PageCount > 0 then
|
|
ActiveSheet.ViewInfo.UpdateViewInfo;
|
|
if HandleAllocated then
|
|
UpdateScrollBars
|
|
else
|
|
if PageCount > 0 then
|
|
ActiveSheet.InitScrollBars;
|
|
if not Listener.IsLocked then Invalidate;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.KeyDown(var Key: Word; Shift: TShiftState);
|
|
|
|
function InKeys(const AKeys: WideString): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := False;
|
|
if Length(AKeys) <> 0 then
|
|
for I := 1 to Length(AKeys) do
|
|
if Result then
|
|
Break
|
|
else
|
|
Result := WideChar(Key) = AKeys[I];
|
|
end;
|
|
|
|
begin
|
|
inherited KeyDown(Key, Shift);
|
|
if PageCount > 0 then
|
|
begin
|
|
if (ssCtrl in Shift) and InKeys('CXVZY') then
|
|
with ActiveSheet do
|
|
begin
|
|
case WideChar(Key) of
|
|
'C':
|
|
Copy(SelectionRect, False);
|
|
'X':
|
|
Copy(SelectionRect, True);
|
|
'V':
|
|
Paste(SelectionRect.TopLeft);
|
|
'Z':
|
|
History.Undo(1);
|
|
'Y':
|
|
History.Redo(1);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
case Key of
|
|
VK_F9:
|
|
try
|
|
FFormulasCache.Lock := False;
|
|
Recalc;
|
|
finally
|
|
FFormulasCache.Lock := True;
|
|
UpdateControl;
|
|
end;
|
|
else
|
|
if (FCaptureControl = nil) and ViewInfoValid then
|
|
ActiveSheet.KeyDown(Key, Shift);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.KeyPress(var Key: Char);
|
|
begin
|
|
if PageCount > 0 then
|
|
begin
|
|
if (FCaptureControl = nil) and ViewInfoValid then
|
|
ActiveSheet.KeyPress(Key);
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.KeyUp(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
if PageCount > 0 then
|
|
begin
|
|
if (FCaptureControl = nil) and ViewInfoValid then
|
|
ActiveSheet.KeyUp(Key, Shift);
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.Loaded;
|
|
begin
|
|
inherited;
|
|
AdjustControls;
|
|
if Assigned(FCaptionBar) then
|
|
FCaptionBar.RecalcViewInfo;
|
|
UpdateControl;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
R: TRect;
|
|
begin
|
|
FMousePos := Point(X, Y);
|
|
if PageCount > 0 then
|
|
begin
|
|
if (FCaptureControl = FCaptionBar) or
|
|
((FCaptureControl = nil) and PtInRect(FCaptionBar.BoundsRect, Point(X, Y))) then
|
|
FCaptionBar.MouseMove(Shift, X, Y - FCaptionBar.Top)
|
|
else
|
|
if ViewInfoValid then
|
|
begin
|
|
ActiveSheet.MouseMove(Shift, X, Y);
|
|
FShift := Shift;
|
|
R.BottomRight := ActiveSheet.ClientRect.BottomRight;
|
|
R.TopLeft := Point(RowHeaderWidth, ColHeaderHeight);
|
|
FTimer.Enabled := not PtInRect(R, FMousePos);
|
|
end;
|
|
end;
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.MouseDown(Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
HitTestInfo: TcxSSHitTestInfo;
|
|
begin
|
|
inherited;
|
|
FContextPopupHandled := False;
|
|
HitTest(Point(X, Y), HitTestInfo);
|
|
if PageCount > 0 then
|
|
begin
|
|
Windows.SetFocus( Handle );
|
|
FMouseDownPos := Point(X, Y);
|
|
if FCaptionBar.Visible and PtInRect(FCaptionBar.BoundsRect, Point(X, Y)) then
|
|
begin
|
|
FCaptionBar.MouseDown(Button, Shift, X, Y - FCaptionBar.Top);
|
|
if Button <> mbRight then
|
|
FCaptureControl := FCaptionBar;
|
|
end
|
|
else
|
|
begin
|
|
if Button <> mbRight then
|
|
FCaptureControl := ActiveSheet;
|
|
if ViewInfoValid then
|
|
begin
|
|
ActiveSheet.MouseDown(Button, Shift, X, Y);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.MouseUp(Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
FTimer.Enabled := False;
|
|
{$IFNDEF DELPHI5}
|
|
if FContextPopupHandled then
|
|
begin
|
|
FContextPopupHandled := False;
|
|
Exit;
|
|
end;
|
|
{$ENDIF}
|
|
inherited;
|
|
if PageCount > 0 then
|
|
begin
|
|
if (FCaptionBar.Visible and PtInRect(FCaptionBar.BoundsRect, Point(X, Y))) or
|
|
((FCaptionBar <> nil) and (FCaptureControl = FCaptionBar)) then
|
|
FCaptionBar.MouseUp(Button, Shift, X, Y - FCaptionBar.Top)
|
|
else
|
|
if ViewInfoValid then
|
|
ActiveSheet.MouseUp(Button, Shift, X, Y);
|
|
FCaptureControl := nil;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.OnChangeHeaderStyle(Sender: TObject);
|
|
begin
|
|
if ViewInfoValid then
|
|
ActiveSheet.ViewInfo.UpdateViewInfo;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.OnMouseTimerHandle(Sender: TObject);
|
|
begin
|
|
with FMousePos do
|
|
MouseMove(FShift, X, Y);
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.Resize;
|
|
begin
|
|
inherited Resize;
|
|
AdjustControls;
|
|
if Assigned(FPaintBitmap) then
|
|
begin
|
|
FPaintBitmap.Height := Height;
|
|
FPaintBitmap.Width := Width;
|
|
end;
|
|
if (FCaptionBar <> nil) and (FCaptionBar.FCaptionEditor <> nil) or
|
|
(PageCount > 0) and (ActiveSheet.CellEditor <> nil) and CanFocus then SetFocus;
|
|
UpdateScrollBars;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.AddSheet(const AName: string;
|
|
AVisible: Boolean): IcxBookSheet;
|
|
begin
|
|
AddSheetPage(AName);
|
|
Supports(TObject(Pages[PageCount - 1]), IcxBookSheet, Result);
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetActiveCell: TPoint;
|
|
begin
|
|
Result := ActiveSheet.ActiveCell;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetActiveSheet: TcxSSBookSheet;
|
|
begin
|
|
Result := Pages[FActivePage];
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetAutoReCalc: Boolean;
|
|
begin
|
|
Result := not FFormulasCache.Lock
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetCell(APage: Word;
|
|
ACol, ARow: Integer): IcxSpreadSheetCell;
|
|
begin
|
|
Result := Pages[APage].GetCell(ACol, ARow)
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetDefinedNames: TcxSSNamesDef;
|
|
begin
|
|
Result := FFormulasCache.Names;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetDefaultStyle: TcxSSDefaultStyle;
|
|
begin
|
|
Result := FStyleCache.DefaultStyle;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetPage(APage: Integer): TcxSSBookSheet;
|
|
begin
|
|
try
|
|
Result := TcxSSBookSheet(FPages[APage]);
|
|
except
|
|
raise ESpreadSheetError.Create(cxGetResourceString(@scxSpreadSheetInvalidSheetNumber));
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetPageCount: Word;
|
|
begin
|
|
if not Assigned(FPages) then
|
|
Result := 0
|
|
else
|
|
Result := FPages.Count;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetPageSelection(APage: Word): TRect;
|
|
begin
|
|
Result := Pages[APage].SelectionRect;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetPageVisible(APage: Word): Boolean;
|
|
begin
|
|
if APage >= Length(FPageVisible) then
|
|
Result := False
|
|
else
|
|
Result := FPageVisible[APage]
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetRCRefStyle: Boolean;
|
|
begin
|
|
Result := FFormulasCache.RCRefStyle;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetSelection: TRect;
|
|
begin
|
|
Result := ActiveSheet.SelectionRect;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetSheet(APage: Word): IcxBookSheet;
|
|
begin
|
|
Supports(TObject(Pages[APage]), IcxBookSheet, Result);
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.GetShowHeaders: Boolean;
|
|
begin
|
|
Result := ActiveSheet.ShowHeaders;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetPalette(
|
|
const APalette: PcxExcelPalette);
|
|
begin
|
|
FPalette := APalette^;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetProtection(Value: Boolean);
|
|
begin
|
|
FProtected := Value;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetActiveCell(const AValue: TPoint);
|
|
begin
|
|
ActiveSheet.ActiveCell := AValue;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetActivePage(AValue: Integer);
|
|
var
|
|
ACanSelect: Boolean;
|
|
const
|
|
AState: array[Boolean] of TcxSSCaptionStates = ([], [csCurrent]);
|
|
begin
|
|
if (FActivePage = AValue) or (AValue < 0) or (AValue >= PageCount) then Exit;
|
|
while not FPageVisible[AValue] and (AValue < (PageCount - 1)) do Inc(AValue);
|
|
while not FPageVisible[AValue] and (AValue > 0) do Dec(AValue);
|
|
ACanSelect := True;
|
|
Listener.OnActiveSheetChanging(Self, AValue, ACanSelect);
|
|
if ACanSelect then
|
|
begin
|
|
if (FCellEditor <> nil) and FCellEditor.Focused then SetFocus;
|
|
if AValue >= Length(FCaptionBar.ViewInfo.Bricks) then
|
|
FCaptionBar.RecalcViewInfo;
|
|
if FActivePage >= 0 then
|
|
FCaptionBar.UpdateCaptionInfo(FActivePage, []);
|
|
Pages[AValue].SetBounds(ClientBounds.Top, ClientBounds.Left,
|
|
ClientBounds.Right, ClientBounds.Bottom);
|
|
Pages[AValue].Visible := True;
|
|
if FActivePage >= 0 then
|
|
Pages[FActivePage].Visible := False;
|
|
FCaptionBar.UpdateCaptionInfo(AValue, [csCurrent]);
|
|
FActivePage := AValue;
|
|
ActiveSheet.SelectionRect := ActiveSheet.DataStorage.CheckSelectionRect(ActiveSheet.SelectionRect);
|
|
if ViewInfoValid then
|
|
ActiveSheet.ViewInfo.UpdateViewInfo;
|
|
FCaptionBar.MakeTabVisible(FActivePage);
|
|
ActiveSheet.Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetAutoRecalc(const AValue: Boolean);
|
|
begin
|
|
if Assigned(FFormulasCache) then
|
|
begin
|
|
if (AValue and not FFormulasCache.Lock) or (not AValue and FFormulasCache.Lock) then Exit;
|
|
FFormulasCache.Lock := not AValue;
|
|
if AValue then ReCalc;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetBufferedPaint(const AValue: Boolean);
|
|
begin
|
|
if FBufferedPaint <> AValue then
|
|
begin
|
|
FBufferedPaint := AValue;
|
|
if AValue then
|
|
begin
|
|
if FPaintBitmap = nil then
|
|
FPaintBitmap := TBitmap.Create;
|
|
FPaintBitmap.Width := Width;
|
|
FPaintBitmap.Height := Height;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetCustomPainter(const AValue: TcxSSCustomPaintEvent);
|
|
begin
|
|
FOnCustomPaint := AValue;
|
|
if Assigned(FPainter) then FPainter.Free;
|
|
FPainter := GetPainterClass.Create;
|
|
if PageCount > 0 then ActiveSheet.Invalidate;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetColHeaderHeight(const AValue: Integer);
|
|
begin
|
|
if (AValue <= 0) or (AValue = FColHeaderHeight) then Exit;
|
|
FColHeaderHeight := AValue;
|
|
if ViewInfoValid then
|
|
ActiveSheet.ViewInfo.UpdateViewInfo;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetDefaultColWidth(const AValue: TcxSSSize);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if AValue = FDefaultColWidth then Exit;
|
|
FDefaultColWidth := AValue;
|
|
for I := 0 to PageCount - 1 do
|
|
Pages[I].DataStorage.Headers[htCol].DefaultSize := AValue;
|
|
if ViewInfoValid then
|
|
ActiveSheet.ViewInfo.UpdateViewInfo;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetDefaultStyle(const AStyle: PcxSSCellStyleRec);
|
|
var
|
|
AFontPtr: PcxSSFontRec;
|
|
begin
|
|
AFontPtr := FStyleCache.Styles[0]^.FontPtr;
|
|
DeleteObject(AFontPtr^.FontHandle);
|
|
AStyle^.FontPtr^.FontHandle := CreateFontHandle(AStyle^.FontPtr);
|
|
AFontPtr^ := AStyle^.FontPtr^;
|
|
FStyleCache.Styles[0]^ := AStyle^;
|
|
TcxStyleAccess(FStyleCache.DefaultStyle).StyleInfo := FStyleCache.Styles[0]^;
|
|
FStyleCache.Styles[0]^.FontPtr := AFontPtr;
|
|
FStyleCache.Styles[0]^.RefCount := 1;
|
|
TcxStyleAccess(DefaultStyle).StyleInfo := FStyleCache.Styles[0]^;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetDefaultStyleProperty(AValue: TcxSSDefaultStyle);
|
|
begin
|
|
FStyleCache.DefaultStyle.Assign(AValue);
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetDefaultRowHeight(const AValue: TcxSSSize);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if AValue = FDefaultRowHeight then Exit;
|
|
FDefaultRowHeight := AValue;
|
|
for I := 0 to PageCount - 1 do
|
|
Pages[I].DataStorage.Headers[htRow].DefaultSize := AValue;
|
|
if ViewInfoValid then
|
|
ActiveSheet.ViewInfo.UpdateViewInfo;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetDefaultColor(const AValue: TColor);
|
|
begin
|
|
if FWindowColor = AValue then Exit;
|
|
FWindowColor := AValue;
|
|
Canvas.WindowColor := Canvas.GetNativeColor(FWindowColor);
|
|
if not Listener.IsLocked then
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetFloatPrecision(const AValue: Byte);
|
|
begin
|
|
if FFloatPrecision <> AValue then
|
|
begin
|
|
FFloatPrecision := AValue;
|
|
UpdateControl;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetGridColor(const AValue: TColor);
|
|
begin
|
|
if AValue <> FGridColor then
|
|
begin
|
|
FGridColor := AValue;
|
|
Canvas.BorderColor := Canvas.GetNativeColor(FGridColor);
|
|
if not Listener.IsLocked then
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetHeaderFont(AValue: TFont);
|
|
begin
|
|
if not Assigned(AValue) then Exit;
|
|
FHeaderFont.Assign(AValue);
|
|
AdjustControls;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetHeaderColor(const AValue: TColor);
|
|
begin
|
|
if AValue <> FHeaderColor then
|
|
begin
|
|
FHeaderColor := AValue;
|
|
if ViewInfoValid then
|
|
PInteger(@ActiveSheet.ViewInfo.InfoData.HeaderColor)^ :=
|
|
Canvas.GetNativeColor(FHeaderColor);
|
|
if not Listener.IsLocked then
|
|
Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetPainterType(const AValue: TcxSSPainterType);
|
|
begin
|
|
if AValue = FPainterType then Exit;
|
|
FPainterType := AValue;
|
|
if Assigned(FPainter) then FPainter.Free;
|
|
FPainter := GetPainterClass.Create;
|
|
if ViewInfoValid then
|
|
ActiveSheet.ViewInfo.InfoChanged := True;
|
|
if not Listener.IsLocked then
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetPageCount(const AValue: Word);
|
|
var
|
|
I, ACount: Integer;
|
|
begin
|
|
if PageCount <> AValue then
|
|
try
|
|
BeginUpdate;
|
|
ACount := PageCount;
|
|
if ACount > AValue then
|
|
begin
|
|
for I := AValue to ACount - 1 do
|
|
begin
|
|
Pages[AValue]._Release;
|
|
FPages.Delete(AValue);
|
|
end;
|
|
ActivePage := 0;
|
|
end
|
|
else
|
|
if ACount < AValue then
|
|
begin
|
|
ACount := PageCount;
|
|
for I := ACount to AValue - 1 do
|
|
AddSheetPage;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
FCaptionBar.Invalidate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetPageSelection(APage: Word;
|
|
const AValue: TRect);
|
|
begin
|
|
Pages[APage].SelectionRect := AValue;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetPageVisible(APage: Word;
|
|
const AValue: Boolean);
|
|
begin
|
|
FPageVisible[APage] := AValue;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetRCRefStyle(const AValue: Boolean);
|
|
begin
|
|
if AValue <> FFormulasCache.RCRefStyle then
|
|
begin
|
|
FFormulasCache.RCRefStyle := AValue;
|
|
UpdateControl;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetReadOnly(const AValue: Boolean);
|
|
begin
|
|
if AValue <> FReadOnly then
|
|
begin
|
|
DefaultStyle.ReadOnly := AValue;
|
|
FReadOnly := AValue;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.Scroll(AScrollBarKind: TScrollBarKind;
|
|
AScrollCode: TScrollCode; var AScrollPos: Integer);
|
|
begin
|
|
inherited Scroll(AScrollBarKind, AScrollCode, AScrollPos);
|
|
if ViewInfoValid then
|
|
begin
|
|
ActiveSheet.Scroll(AScrollBarKind, AScrollCode, AScrollPos);
|
|
ActiveSheet.InitScrollBars;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.SpreadSheetClipboardDataToData(
|
|
ASheet: TcxSSBookSheet; const AColPos, ARowPos: Integer; out AChangedRect: TRect): Boolean;
|
|
|
|
var
|
|
DC, DR: Integer;
|
|
|
|
procedure SetCellData(ACol, ARow: Integer; const AData: AnsiString);
|
|
var
|
|
ADataSize: Integer;
|
|
ACell: TcxSSCellRec;
|
|
AFont: TcxSSFontRec;
|
|
ASide: TcxSSEdgeBorder;
|
|
IsFuncValid: Boolean;
|
|
|
|
procedure GetBuf(var Buf; ASize: Integer);
|
|
begin
|
|
Move(AData[ADataSize], Buf, ASize);
|
|
Inc(ADataSize, ASize);
|
|
end;
|
|
|
|
function GetByte: Byte;
|
|
begin
|
|
GetBuf(Result, SizeOf(Result));
|
|
end;
|
|
|
|
function GetWord: Word;
|
|
begin
|
|
GetBuf(Result, SizeOf(Result));
|
|
end;
|
|
|
|
function GetString: string;
|
|
var
|
|
ASize: Integer;
|
|
begin
|
|
GetBuf(ASize, SizeOf(ASize));
|
|
SetLength(Result, ASize div SizeOf(Char));
|
|
if ASize > 0 then
|
|
GetBuf(Result[1], ASize);
|
|
end;
|
|
|
|
begin
|
|
if AData <> '' then
|
|
begin
|
|
IsFuncValid := True;
|
|
ADataSize := 1;
|
|
with ASheet.GetCellObject(ACol, ARow) do
|
|
try
|
|
if not CanModify(ASheet.Owner, ASheet, ACol, ARow) then Exit;
|
|
with TcxStyleAccess(Style).StyleInfo do
|
|
begin
|
|
CellState := [];
|
|
GetBuf(FormatIndex, SizeOf(FormatIndex));
|
|
GetBuf(HorzAlign, SizeOf(HorzAlign));
|
|
GetBuf(VertAlign, SizeOf(VertAlign));
|
|
GetBuf(WordBreak, SizeOf(WordBreak));
|
|
GetBuf(ShrinkToFit, SizeOf(ShrinkToFit));
|
|
GetBuf(BrushStyle, SizeOf(BrushStyle));
|
|
GetBuf(BrushFgColor, SizeOf(BrushFgColor));
|
|
GetBuf(BrushBkColor, SizeOf(BrushBkColor));
|
|
AFont.Name := GetString;
|
|
AFont.FontColor := GetWord;
|
|
Byte(AFont.Style) := GetByte;
|
|
Byte(AFont.Charset) := GetByte;
|
|
AFont.Size := SmallInt(GetByte);
|
|
with Style.Font do
|
|
AssignInfo(AFont.Name, AFont.Size, AFont.Style, AFont.Charset, AFont.FontColor);
|
|
TcxStyleAccess(Style).DoOnChange(Style, siAll);
|
|
for ASide := eLeft to eBottom do
|
|
begin
|
|
Borders[ASide].Style := TcxSSEdgeLineStyle(GetByte);
|
|
Borders[ASide].Color := GetWord;
|
|
TcxStyleAccess(Style).DoOnChange(Style.Borders[ASide], siBorder);
|
|
end;
|
|
GetBuf(CellState, SizeOf(TcxSSCellStates));
|
|
TcxStyleAccess(Style).DoOnChange(Style, siAll);
|
|
end;
|
|
finally
|
|
Free;
|
|
end;
|
|
ACell := ASheet.DataStorage[ACol, ARow];
|
|
with ACell do
|
|
try
|
|
if (DataType = dtFunction) and (FuncRecPtr <> nil) then
|
|
begin
|
|
FormulasCache.DestroyFunction(FuncRecPtr);
|
|
FuncRecPtr := nil;
|
|
{ FreeMem(FuncRecPtr^.CalcResult.Tokens);
|
|
FreeMem(FuncRecPtr^.FuncTree.Tokens);
|
|
FillChar(FuncRecPtr^.FuncTree, SizeOf(TcxStackItem), 0);
|
|
FillChar(FuncRecPtr^.CalcResult, SizeOf(TcxStackItem), 0);}
|
|
end;
|
|
GetBuf(DataType, SizeOf(DataType));
|
|
if DataType = dtDateTime then
|
|
GetBuf(DateTime, SizeOf(DateTime))
|
|
else
|
|
if DataType = dtFunction then
|
|
begin
|
|
if FuncRecPtr = nil then
|
|
begin
|
|
New(FuncRecPtr);
|
|
FillChar(FuncRecPtr^, SizeOf(TcxSSFuncRec), 0);
|
|
FuncRecPtr^.Col := ACol;
|
|
FuncRecPtr^.Row := ARow;
|
|
FuncRecPtr^.Page := FPages.IndexOf(ASheet);
|
|
end;
|
|
with FuncRecPtr^ do
|
|
begin
|
|
States := fsSource;
|
|
GetBuf(FuncRecPtr^.FuncTree.Size, SizeOf(FuncRecPtr^.FuncTree.Size));
|
|
GetMem(FuncRecPtr^.FuncTree.Tokens, FuncRecPtr^.FuncTree.Size);
|
|
GetBuf(FuncRecPtr^.FuncTree.Tokens^, FuncRecPtr^.FuncTree.Size);
|
|
end;
|
|
FFormulasCache.Add(FuncRecPtr);
|
|
IsFuncValid := FFormulasCache.ValidateRef(FuncRecPtr);
|
|
FFormulasCache.UpdateExternalLinks(FuncRecPtr, DR, DC);
|
|
Text := FFormulasCache.FuncHandler.TokensToString(FuncRecPtr);
|
|
end;
|
|
if DataType <> dtFunction then
|
|
Text := GetString;
|
|
finally
|
|
TcxDataStorageAccess(ASheet.DataStorage).SetCellRec(ACol, ARow, ACell);
|
|
if not IsFuncValid then
|
|
TcxDataStorageAccess(ASheet.DataStorage).SetCellTextEx(ACol, ARow, scxRefError);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
S, S1: AnsiString;
|
|
R: TRect;
|
|
ALen, APos: Integer;
|
|
DX, DY, I, J: Integer;
|
|
MergedCells: TcxSSRectsArray;
|
|
begin
|
|
S := cxSSClipboard.DataAsEssFormat;
|
|
Result := Length(S) > 0;
|
|
if Result then
|
|
try
|
|
APos := 1;
|
|
Move(S[1], R, SizeOf(R));
|
|
Inc(APos, SizeOf(R));
|
|
DX := R.Right - R.Left;
|
|
DY := R.Bottom - R.Top;
|
|
with TcxDataStorageAccess(ASheet.DataStorage).MergedCells do
|
|
Result := IntersectMerge(Rect(AColPos, ARowPos, AColPos + DX + 1, ARowPos + DY + 1));
|
|
if Result then
|
|
raise ESpreadSheetError.Create(cxGetResourceString(@scxChangePartOfMergeCells))
|
|
else
|
|
Result := True;
|
|
ALen := PInteger(@S[APos])^;
|
|
Inc(APos, SizeOf(Integer));
|
|
if ALen > 0 then
|
|
begin
|
|
SetLength(MergedCells, ALen);
|
|
Move(S[APos], MergedCells[0], ALen * SizeOf(TRect));
|
|
for I := 0 to ALen - 1 do
|
|
OffsetRect(MergedCells[I], AColPos - R.Left, ARowPos - R.Top);
|
|
Inc(APos, ALen shl 4);
|
|
end;
|
|
DC := AColPos - R.Left;
|
|
DR := ARowPos - R.Top;
|
|
for I := AColPos to AColPos + DX do
|
|
begin
|
|
for J := ARowPos to ARowPos + DY do
|
|
begin
|
|
Move(S[APos], ALen, SizeOf(ALen));
|
|
Inc(APos, SizeOf(ALen));
|
|
if (ALen + APos) < Length(S) then
|
|
begin
|
|
if ALen > 0 then
|
|
begin
|
|
SetLength(S1, ALen);
|
|
Move(S[APos], S1[1], ALen);
|
|
SetCellData(I, J, S1);
|
|
end;
|
|
Inc(APos, ALen);
|
|
end
|
|
else
|
|
Break;
|
|
end;
|
|
end;
|
|
AChangedRect := Rect(AColPos, ARowPos, AColPos + DX, ARowPos + DY);
|
|
with TcxDataStorageAccess(ASheet.DataStorage).MergedCells do
|
|
AddMerges(MergedCells);
|
|
finally
|
|
with TcxDataStorageAccess(ASheet.DataStorage) do
|
|
begin
|
|
if CheckInMergeRange(Point(AColPos, ARowPos), R) then
|
|
SelectionRect := R;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.SpreadSheetDataToClipboardData(
|
|
ASheet: TcxSSBookSheet; const ACells: TRect): AnsiString;
|
|
|
|
function GetCellData(ACol, ARow: Integer): AnsiString;
|
|
var
|
|
ADataSize: Integer;
|
|
ACapacity: Integer;
|
|
APtr: PByteArray;
|
|
const
|
|
Null: Integer = 0;
|
|
|
|
procedure ReallocBuf(NeedSize: Integer);
|
|
begin
|
|
while (ADataSize + NeedSize) >= ACapacity do
|
|
Inc(ACapacity, 2048);
|
|
ReallocMem(APtr, ACapacity);
|
|
end;
|
|
|
|
procedure WriteBuf(const Buf; ASize: Integer; WriteSize: Boolean = False);
|
|
begin
|
|
if WriteSize then
|
|
begin
|
|
ReallocBuf(SizeOf(Integer));
|
|
Move(ASize, APtr^[ADataSize], SizeOf(Integer));
|
|
Inc(ADataSize, SizeOf(Integer));
|
|
end;
|
|
ReallocBuf(ASize);
|
|
if ASize <> 0 then
|
|
begin
|
|
Move(Buf, APtr^[ADataSize], ASize);
|
|
Inc(ADataSize, ASize);
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
with ASheet.DataStorage[ACol, ARow] do
|
|
begin
|
|
ADataSize := 0;
|
|
ACapacity := 0;
|
|
APtr := nil;
|
|
try
|
|
with StylePtr^ do
|
|
begin
|
|
WriteBuf(FormatIndex, SizeOf(FormatIndex));
|
|
WriteBuf(HorzAlign, SizeOf(HorzAlign));
|
|
WriteBuf(VertAlign, SizeOf(VertAlign));
|
|
WriteBuf(WordBreak, SizeOf(WordBreak));
|
|
WriteBuf(ShrinkToFit, SizeOf(ShrinkToFit));
|
|
WriteBuf(BrushStyle, SizeOf(BrushStyle));
|
|
WriteBuf(BrushFgColor, SizeOf(BrushFgColor));
|
|
WriteBuf(BrushBkColor, SizeOf(BrushBkColor));
|
|
with FontPtr^ do
|
|
begin
|
|
WriteBuf(Name[1], Length(Name) * SizeOf(Char), True);
|
|
WriteBuf(FontColor, SizeOf(FontColor));
|
|
WriteBuf(Style, SizeOf(Style));
|
|
WriteBuf(Charset, SizeOf(Charset));
|
|
WriteBuf(Size, SizeOf(Size));
|
|
end;
|
|
WriteBuf(Borders, SizeOf(Borders));
|
|
WriteBuf(CellState, SizeOf(TcxSSCellStates));
|
|
end;
|
|
WriteBuf(DataType, SizeOf(DataType));
|
|
if DataType = dtDateTime then
|
|
WriteBuf(DateTime, SizeOf(DateTime))
|
|
else
|
|
if (DataType = dtFunction) and (FuncRecPtr <> nil) and (FuncRecPtr^.FuncTree.Size <> 0) then
|
|
begin
|
|
WriteBuf(FuncRecPtr^.FuncTree.Size, SizeOf(FuncRecPtr^.FuncTree.Size));
|
|
WriteBuf(FuncRecPtr^.FuncTree.Tokens^, FuncRecPtr^.FuncTree.Size);
|
|
end;
|
|
if Length(Text) > 0 then
|
|
WriteBuf(Text[1], Length(Text) * SizeOf(Char), True)
|
|
else
|
|
WriteBuf(Null, SizeOf(Integer));
|
|
finally
|
|
SetLength(Result, ADataSize + SizeOf(Integer));
|
|
Move(ADataSize, Result[1], SizeOf(Integer));
|
|
Move(APtr^, Result[5], ADataSize);
|
|
FreeMem(APtr);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I, J: Integer;
|
|
MergedCells: TcxSSRectsArray;
|
|
begin
|
|
with TcxDataStorageAccess(ASheet.DataStorage).MergedCells do
|
|
MergedCells := IntersectMergedCells(Rect(ACells.Left, ACells.Top, ACells.Right + 1, ACells.Bottom + 1));
|
|
SetLength(Result, SizeOf(Integer) + (Length(MergedCells) + 1) * SizeOf(TRect));
|
|
Move(ACells, Result[1], SizeOf(ACells));
|
|
PInteger(@Result[1 + SizeOf(ACells)])^ := Length(MergedCells);
|
|
if Length(MergedCells) > 0 then
|
|
Move(MergedCells[0], Result[5 + SizeOf(ACells)], Length(MergedCells) * SizeOf(TRect));
|
|
TcxHistoryAccess(History).BeginUpdate;
|
|
try
|
|
for I := ACells.Left to ACells.Right do
|
|
for J := ACells.Top to ACells.Bottom do
|
|
Result := Result + GetCellData(I, J);
|
|
finally
|
|
TcxHistoryAccess(History).EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.VisibleChanging;
|
|
begin
|
|
inherited;
|
|
UpdateControl;
|
|
AdjustControls;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetModified;
|
|
begin
|
|
FModified := True;
|
|
end;
|
|
|
|
function TcxCustomSpreadSheetBook.ViewInfoValid: Boolean;
|
|
begin
|
|
Result := (PageCount > 0) and ActiveSheet.ViewInfoValid;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetRowHeaderWidth(const AValue: Integer);
|
|
begin
|
|
if (AValue = FRowHeaderWidth) or (AValue <= 0) then Exit;
|
|
FRowHeaderWidth := AValue;
|
|
if ViewInfoValid then
|
|
ActiveSheet.ViewInfo.UpdateViewInfo;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetSelectionColor(const AValue: TColor);
|
|
begin
|
|
if FSelectionColor = AValue then Exit;
|
|
FSelectionColor := AValue;
|
|
Canvas.SelectionColor := Canvas.GetNativeColor(FSelectionColor);
|
|
if not Listener.IsLocked then
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetScrollBars(const AValue: TcxScrollBars);
|
|
const
|
|
AVisibleState: array[TcxScrollBars, 0..1] of Boolean =
|
|
((False, False), (True, False), (False, True), (True, True));
|
|
begin
|
|
if AValue <> FScrollBars then
|
|
begin
|
|
FScrollBars := AValue;
|
|
AdjustControls;
|
|
if not Listener.IsLocked then
|
|
InvalidateRect(Rect(0, Height - Max(FCaptionBar.Height, HScrollBar.Height),
|
|
Width, Height), False);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetShowCaptionBar(const AValue: Boolean);
|
|
begin
|
|
if FShowCaptionBar = AValue then Exit;
|
|
FShowCaptionBar := AValue;
|
|
FCaptionBar.Visible := AValue;
|
|
if AValue then
|
|
FCaptionBar.RecalcViewInfo;
|
|
AdjustControls;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetShowFormulas(const AValue: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
if FShowFormulas = AValue then Exit;
|
|
FShowFormulas := AValue;
|
|
for I := 0 to PageCount - 1 do
|
|
Pages[I].ShowFormulas := AValue;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetShowHeaders(const AValue: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to PageCount - 1 do
|
|
Pages[I].FShowHeaders := AValue;
|
|
if ViewInfoValid then
|
|
ActiveSheet.ViewInfo.UpdateViewInfo;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetSelection(const AValue: TRect);
|
|
begin
|
|
ActiveSheet.SelectionRect := AValue;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.SetShowGrid(const AValue: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
FShowGrid := AValue;
|
|
for I := 0 to PageCount - 1 do
|
|
Pages[I].ShowGrid := AValue;
|
|
end;
|
|
|
|
procedure TcxCustomSpreadSheetBook.CM_CHANGELOCALE(var Message: TMessage);
|
|
begin
|
|
inherited;
|
|
if IsWinNT then
|
|
CurrencyString := GetLocaleStrW(GetThreadLocale, LOCALE_SCURRENCY);
|
|
GetFormatSettings;
|
|
SetControlCodes;
|
|
UpdateControl;
|
|
end;
|
|
|
|
{$IFNDEF DELPHI5}
|
|
procedure TcxCustomSpreadSheetBook.WMRButtonUp(var Message: TWMRButtonUp);
|
|
begin
|
|
with Message do
|
|
begin
|
|
if Assigned(OnContextPopup) and not FContextPopupHandled then
|
|
OnContextPopup(Self, ScreenToClient(Point(XPos, YPos)), FContextPopupHandled);
|
|
if FContextPopupHandled then
|
|
Result := 1
|
|
else
|
|
inherited;
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{ TcxSSBookPageCaptions }
|
|
constructor TcxSSBookPageCaptions.Create(AOwner: TcxCustomSpreadSheetBook);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FCaptionPainter := Owner.GetCaptionPainterClass.Create;
|
|
FViewInfo.FirstVisibleCaption := 0;
|
|
end;
|
|
|
|
destructor TcxSSBookPageCaptions.Destroy;
|
|
begin
|
|
FCaptionPainter.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.MakeTabVisible(AIndex: Integer);
|
|
|
|
function IsVisible: Integer;
|
|
var
|
|
W: Integer;
|
|
R: TRect;
|
|
begin
|
|
if (AIndex < 0) or (AIndex >= Length(FViewInfo.Bricks)) then
|
|
begin
|
|
Result := 0;
|
|
Exit;
|
|
end;
|
|
R := FViewInfo.Bricks[AIndex].BoundsRect;
|
|
Result := FirstVisibleCaption - AIndex;
|
|
if Result > 0 then
|
|
Result := -1
|
|
else
|
|
if Result < 0 then
|
|
Result := 1;
|
|
if Result > 0 then
|
|
begin
|
|
if Owner.HScrollBar.Visible then
|
|
W := Owner.Width shr 1
|
|
else
|
|
W := Owner.Width;
|
|
if R.Right < W then
|
|
Result := 0;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
while IsVisible <> 0 do
|
|
FirstVisibleCaption := FirstVisibleCaption + IsVisible;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.ActivateEditor;
|
|
var
|
|
ARect: TRect;
|
|
begin
|
|
if FCaptionEditor = nil then
|
|
begin
|
|
FCaptionEditor :=
|
|
Owner.GetInplaceEditClass.Create(Owner, False) as TcxSSInplaceTextEdit;
|
|
FCaptionEditor.Parent := Owner;
|
|
FCaptionEditor.WantTab := True;
|
|
FCaptionEditor.OnEndEdit := OnEndEditCaption;
|
|
FCaptionEditor.OnChange := OnEditCaptionText;
|
|
end;
|
|
FCaptionEditor.Font.Assign(Owner.HeaderFont);
|
|
ARect := FViewInfo.Bricks[Owner.ActivePage].BoundsRect;
|
|
OffsetRect(ARect, 13, 0);
|
|
FCaptionEditor.SetBounds(ARect.Left + 2, ARect.Top + 2,
|
|
ARect.Right - ARect.Left - 2, ARect.Bottom - ARect.Top - 2);
|
|
with Owner.ActiveSheet do
|
|
FCaptionEditor.InitEditor(Caption, Caption);
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.DblClick;
|
|
var
|
|
AIndex: Integer;
|
|
begin
|
|
if HitTest(FMouseDownPos.X, FMouseDownPos.Y, AIndex) <> htCaption then Exit;
|
|
if Owner.ActivePage < 0 then Exit;
|
|
with Owner.ActiveSheet.SelectionRect do
|
|
if CanModify(Owner, Owner.ActiveSheet, Left, Top) then
|
|
begin
|
|
ActivateEditor;
|
|
FIsEditorActivate := True;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.DoEditCaption;
|
|
|
|
function SheetRectIsVisible(const ARect: TRect): Boolean;
|
|
var
|
|
W: Integer;
|
|
begin
|
|
if Owner.HScrollBar.Visible then
|
|
W := Owner.Width shr 1
|
|
else
|
|
W := Owner.Width;
|
|
Result := ARect.Right < W;
|
|
end;
|
|
|
|
begin
|
|
if Owner.ActivePage < FirstVisibleCaption then
|
|
FirstVisibleCaption := Owner.ActivePage;
|
|
while (FirstVisibleCaption < Owner.ActivePage) and
|
|
not SheetRectIsVisible(FViewInfo.Bricks[Owner.ActivePage].BoundsRect) do
|
|
begin
|
|
FirstVisibleCaption := FirstVisibleCaption + 1;
|
|
end;
|
|
ActivateEditor;
|
|
FCaptionEditor.SetFocus;
|
|
end;
|
|
|
|
function TcxSSBookPageCaptions.GetCaptionTextExtent(APage: Integer): TRect;
|
|
var
|
|
I: Byte;
|
|
begin
|
|
Canvas.SelectFont(Owner.HeaderFont);
|
|
with FViewInfo do
|
|
begin
|
|
Result := Rect(0, Bounds.Top, 0, Bounds.Bottom - 1);
|
|
for I := FirstVisibleCaption to APage do
|
|
if csHidden in Bricks[I].State then
|
|
Continue
|
|
else
|
|
begin
|
|
Result.Left := Result.Right;
|
|
if Owner.HandleAllocated then
|
|
Result.Right := Result.Left +
|
|
Canvas.TextWidth(Bricks[I].DisplayText) + 30;
|
|
if Result.Left > 0 then OffsetRect(Result, -10, 0);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TcxSSBookPageCaptions.HitTest(X, Y: Integer;
|
|
var AIndex: Integer): TcxSSCaptionHitTest;
|
|
|
|
function CheckHitInCaption(ACaptionRect: TRect; AX, AY: Integer): Boolean;
|
|
var
|
|
DX: Integer;
|
|
begin
|
|
OffsetRect(ACaptionRect, -Left, -Top);
|
|
AX := AX - Left;
|
|
AY := AY - Top;
|
|
DX := Round(AY * 10 / Height);
|
|
Result := (AY > ACaptionRect.Top) and (AY < ACaptionRect.Bottom) and
|
|
((AX >= (ACaptionRect.Left + DX)) and (AX <= (ACaptionRect.Right - DX)))
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
AHitPoint: TPoint;
|
|
begin
|
|
Result := htNone;
|
|
AIndex := 0;
|
|
AHitPoint := Point(X + Left, Y + Top);
|
|
with FViewInfo do
|
|
begin
|
|
for I := 0 to 3 do
|
|
if PtInRect(BtnBricks[TcxSSNavigatorBtn(I)], AHitPoint) then
|
|
begin
|
|
AIndex := I;
|
|
Result := htButton;
|
|
Exit;
|
|
end;
|
|
AIndex := -1;
|
|
for I := FViewInfo.FirstVisibleCaption to Length(Bricks) - 1 do
|
|
if not (csHidden in Bricks[I].State) then
|
|
begin
|
|
if CheckHitInCaption(Bricks[I].BoundsRect, AHitPoint.X, AHitPoint.Y) then
|
|
begin
|
|
if (AIndex < 0) or (csCurrent in Bricks[I].State) then
|
|
AIndex := I;
|
|
end;
|
|
end;
|
|
if AIndex >=0 then
|
|
Result := htCaption;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
AHitRes: Integer;
|
|
AHitType: TcxSSCaptionHitTest;
|
|
AIsDown: Boolean;
|
|
|
|
begin
|
|
Cursor := crDefault;
|
|
AHitType := HitTest(X, Y, AHitRes);
|
|
with FViewInfo do
|
|
begin
|
|
if BtnDown <> -1 then
|
|
begin
|
|
AIsDown := (AHitType = htButton) and (AHitRes = BtnDown);
|
|
if AIsDown <> IsButtonDown then
|
|
begin
|
|
IsButtonDown := AIsDown;
|
|
if not Owner.Listener.IsLocked then
|
|
Owner.InvalidateRect(BtnBricks[TcxSSNavigatorBtn(BtnDown)], False);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.MouseDown(Button: TMouseButton;
|
|
Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
AHitRes: Integer;
|
|
AHitType: TcxSSCaptionHitTest;
|
|
begin
|
|
if FIsEditorActivate then Exit;
|
|
if Button = mbRight then
|
|
Owner.Listener.OnCaptionPopupMenu(Owner.ActiveSheet,
|
|
ClientToScreen(X, Y))
|
|
else
|
|
with FViewInfo do
|
|
begin
|
|
FMouseDownPos := Point(X, Y);
|
|
AHitType := HitTest(X, Y, AHitRes);
|
|
with Owner do
|
|
begin
|
|
if AHitType = htButton then
|
|
begin
|
|
IsButtonDown := True;
|
|
BtnDown := AHitRes;
|
|
if not Listener.IsLocked then
|
|
InvalidateRect(BtnBricks[TcxSSNavigatorBtn(AHitRes)], False);
|
|
end
|
|
else
|
|
if AHitType = htCaption then
|
|
begin
|
|
FSkipActivePageChanging := True;
|
|
ActivePage := AHitRes;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
var
|
|
AHitRes: Integer;
|
|
AHitType: TcxSSCaptionHitTest;
|
|
ACaption: Integer;
|
|
begin
|
|
inherited;
|
|
if FIsEditorActivate then
|
|
begin
|
|
FIsEditorActivate := False;
|
|
FCaptionEditor.Font.Assign(Owner.HeaderFont);
|
|
FCaptionEditor.SetFocus;
|
|
Exit;
|
|
end;
|
|
FMouseDownPos := Point(X, Y);
|
|
AHitType := HitTest(X, Y, AHitRes);
|
|
if AHitType = htButton then
|
|
begin
|
|
ACaption := FViewInfo.FirstVisibleCaption;
|
|
if FViewInfo.BtnDown = AHitRes then
|
|
begin
|
|
case AHitRes of
|
|
0:
|
|
ACaption := 0;
|
|
1:
|
|
if ACaption > 0 then
|
|
Dec(ACaption);
|
|
2:
|
|
if ACaption < (Owner.PageCount - 1) then
|
|
Inc(ACaption);
|
|
3:
|
|
ACaption := Owner.PageCount - 1;
|
|
end;
|
|
end;
|
|
if not Self.Owner.Listener.IsLocked then
|
|
Self.Owner.InvalidateRect(FViewInfo.BtnBricks[TcxSSNavigatorBtn(FViewInfo.BtnDown)], False);
|
|
FirstVisibleCaption := ACaption;
|
|
end
|
|
else
|
|
if (AHitType = htCaption) and not FSkipActivePageChanging then
|
|
Owner.ActivePage := AHitRes;
|
|
FSkipActivePageChanging := False;
|
|
FViewInfo.IsButtonDown := False;
|
|
FViewInfo.BtnDown := -1;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.OnEditCaptionText(Sender: TObject);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with ViewInfo do
|
|
begin
|
|
Bricks[Owner.ActivePage].DisplayText := (Sender as TcxSSInplaceTextEdit).Text;
|
|
for I := Owner.ActivePage to Owner.PageCount - 1 do
|
|
begin
|
|
Bricks[I].BoundsRect := GetCaptionTextExtent(I);
|
|
OffsetRect(Bricks[I].BoundsRect, BtnBricks[nbEnd].Right, 0);
|
|
end;
|
|
end;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.OnEndEditCaption(Sender: TObject);
|
|
var
|
|
ARect: TRect;
|
|
begin
|
|
if FCaptionEditor.Focused then
|
|
Owner.SetFocus;
|
|
FCaptionEditor.Visible := False;
|
|
try
|
|
Owner.ActiveSheet.Caption := FCaptionEditor.Text;
|
|
finally
|
|
RecalcViewInfo;
|
|
ARect.TopLeft := ViewInfo.Bricks[Owner.ActivePage].BoundsRect.TopLeft;
|
|
ARect.BottomRight := ViewInfo.Bounds.BottomRight;
|
|
if not Owner.Listener.IsLocked then
|
|
Owner.InvalidateRect(ARect, False);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.Paint;
|
|
begin
|
|
FViewInfo.FillColor := Canvas.GetNativeColor(Owner.HeaderColor);
|
|
FViewInfo.Font := Owner.HeaderFont;
|
|
FCaptionPainter.Paint(Canvas, FViewInfo);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.ReCalcViewInfo;
|
|
var
|
|
I: Integer;
|
|
ALeft: Integer;
|
|
const
|
|
AVisibleState: array[Boolean] of TcxSSCaptionStates = ([csHidden], []);
|
|
AActiveState: array[Boolean] of TcxSSCaptionStates = ([], [csCurrent]);
|
|
begin
|
|
if not Owner.HandleAllocated or Owner.Listener.IsLocked then Exit;
|
|
Canvas.BeginPaint(ControlCanvas);
|
|
with FViewInfo do
|
|
begin
|
|
IsButtonDown := False;
|
|
BtnDown := -1;
|
|
Font := Owner.HeaderFont;
|
|
Bounds := Rect(Left, Top, Left + Width, Top + Height);
|
|
SetLength(Bricks, Owner.PageCount);
|
|
Enabled := [nbStart, nbPrev, nbNext, nbEnd];
|
|
for I := 0 to 3 do
|
|
BtnBricks[TcxSSNavigatorBtn(I)] := Rect(Bounds.Left + I * Height, Bounds.Top,
|
|
Bounds.Left + (I + 1) * Height, Bounds.Bottom - 1);
|
|
with FViewInfo do
|
|
begin
|
|
ALeft := BtnBricks[nbEnd].Right;
|
|
for I := FViewInfo.FirstVisibleCaption to Owner.PageCount - 1 do
|
|
begin
|
|
Bricks[I].DisplayText := Owner.Pages[I].Caption;
|
|
Bricks[I].State := AVisibleState[Owner.PageVisible[I]] +
|
|
AActiveState[Owner.ActivePage = I];
|
|
Bricks[I].BoundsRect := GetCaptionTextExtent(I);
|
|
OffsetRect(Bricks[I].BoundsRect, ALeft, 0);
|
|
end;
|
|
end;
|
|
end;
|
|
Canvas.Canvas.Font.Assign(Owner.HeaderFont);
|
|
Height := Canvas.TextHeight('I') + 5;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.Resize;
|
|
begin
|
|
inherited Resize;
|
|
if not EqualRect(ClientRect, FViewInfo.Bounds) then RecalcViewInfo;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.UpdateCaptionInfo(APage: Byte;
|
|
AState: TcxSSCaptionStates);
|
|
begin
|
|
if APage < Length(FViewInfo.Bricks) then
|
|
begin
|
|
with FViewInfo.Bricks[APage] do
|
|
begin
|
|
State := AState;
|
|
InvalidateRect(ClientRect);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.VisibleChanging;
|
|
begin
|
|
if Owner.CaptionBar.Visible then
|
|
Owner.HScrollBar.Left := Owner.CaptionBar.Width
|
|
else
|
|
Owner.HScrollBar.Left := 0
|
|
end;
|
|
|
|
function TcxSSBookPageCaptions.GetFirstVisibleCaption: Integer;
|
|
begin
|
|
Result := FViewInfo.FirstVisibleCaption;
|
|
end;
|
|
|
|
procedure TcxSSBookPageCaptions.SetFirstVisibleCaption(const Value: Integer);
|
|
begin
|
|
if FirstVisibleCaption <> Value then
|
|
begin
|
|
FViewInfo.FirstVisibleCaption := Value;
|
|
RecalcViewInfo;
|
|
InvalidateRect(ClientRect);
|
|
end;
|
|
end;
|
|
|
|
{ TcxSSBookSheet }
|
|
constructor TcxSSBookSheet.Create(AOwner: TcxCustomSpreadSheetBook);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FDataStorage := Owner.GetDataStorageClass.Create(Self);
|
|
FSheetViewInfo := Owner.GetViewInfoClass.Create(Self);
|
|
FShowFormulas := Owner.ShowFormulas;
|
|
FShowGrid := Owner.ShowGrid;
|
|
FShowHeaders := True;
|
|
FSheetState := [];
|
|
FCurrentPos := Point(0, 0);
|
|
FVisible := False;
|
|
end;
|
|
|
|
destructor TcxSSBookSheet.Destroy;
|
|
begin
|
|
try
|
|
FDataStorage.Free;
|
|
FSheetViewInfo.Free;
|
|
finally
|
|
inherited Destroy;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.Assign(Source: TcxSSBookSheet);
|
|
begin
|
|
if Source <> nil then
|
|
begin
|
|
Owner.BeginUpdate;
|
|
try
|
|
FReadOnly := Source.FReadOnly;
|
|
FShowGrid := Source.ShowGrid;
|
|
FShowHeaders := Source.FShowHeaders;
|
|
FShowFormulas := Source.FShowFormulas;
|
|
DataStorage.Assign(Source.DataStorage);
|
|
Cols.Assign(Source.Cols);
|
|
Rows.Assign(Source.Rows);
|
|
finally
|
|
Owner.EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.ClearAll;
|
|
begin
|
|
Owner.DeactivateEditor;
|
|
Owner.History.StartComplexAction(cxGetResourceString(@scxClearAllAction));
|
|
try
|
|
DataStorage.ClearCells(Rect(-1, -1, -1, -1), True);
|
|
finally
|
|
if ViewInfoValid then
|
|
ViewInfo.UpdateViewInfo;
|
|
end;
|
|
Owner.History.StopComplexAction;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.ClearCells(const ARect: TRect;
|
|
SetDefaultStyle: Boolean = False);
|
|
var
|
|
I: Integer;
|
|
StartAction: Boolean;
|
|
begin
|
|
if not CanModify(Owner, Self, ARect) then Exit;
|
|
Owner.DeactivateEditor;
|
|
StartAction := Owner.History.StartComplexAction(cxGetResourceString(@scxClearCells));
|
|
try
|
|
DataStorage.ClearCells(ARect, SetDefaultStyle);
|
|
for I := ARect.Top to ARect.Bottom do ApplyAutoHeight(I);
|
|
finally
|
|
if StartAction then
|
|
Owner.History.StopComplexAction;
|
|
ViewInfo.UpdateViewInfo;
|
|
CellsChanged(ARect);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.DeleteCells(const ACells: TRect; ACellsModify: TcxSSCellsModify);
|
|
begin
|
|
if Owner.ExcelProtectionStyle and not CanModify(Owner, Self, ACells) then Exit;
|
|
with Owner do
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
if ACellsModify in [msAllRow, msAllCol] then
|
|
FormulasCache.UpdateRef(FPages.IndexOf(Self), ACells, True, ACellsModify = msAllCol);
|
|
DataStorage.DeleteCells(ACells, ACellsModify);
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.Copy(const ARect: TRect; IsCut: Boolean);
|
|
var
|
|
I, J: Integer;
|
|
AText: string;
|
|
Action: TcxComplexAction;
|
|
begin
|
|
for J := ARect.Top to ARect.Bottom do
|
|
begin
|
|
for I := ARect.Left to ARect.Right do
|
|
begin
|
|
AText := AText + DataStorage[I, J].Text;
|
|
if I < ARect.Right then
|
|
AText := AText + CellTerminator;
|
|
end;
|
|
if J < ARect.Bottom then
|
|
AText := AText + RowTerminator;
|
|
end;
|
|
cxSSClipboard.DataAsEssFormat := Owner.SpreadSheetDataToClipboardData(Self, ARect) + #13#10;
|
|
cxSSClipboard.DataAsUnicode := AText + #13#10;
|
|
if IsCut and CanModify(Owner, Self, ARect) then
|
|
begin
|
|
TcxHistoryAccess(Owner.History).AddComplexAction(TcxComplexAction, cxGetResourceString(@scxCutCommand), Action);
|
|
try
|
|
DataStorage.ClearCells(ARect);
|
|
finally
|
|
if Action <> nil then
|
|
TcxHistoryAccess(Owner.History).StopComplexAction;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.FormatCells(const ACells: TRect);
|
|
var
|
|
ADesignerClass: TcxSSFormatDialogClass;
|
|
ACanFormat: Boolean;
|
|
AForm: TForm;
|
|
ARect: TRect;
|
|
begin
|
|
ADesignerClass := TcxSSStyleDesigner;
|
|
ACanFormat := True;
|
|
if Assigned(Owner.FOnFormatCells) then
|
|
Owner.OnFormatCells(Owner, PRect(@ACells)^, ACanFormat, ADesignerClass);
|
|
if ACanFormat then
|
|
begin
|
|
History.StartComplexAction(cxGetResourceString(@scxChangeCellsStyle));
|
|
try
|
|
AForm := ADesignerClass.Create(nil);
|
|
ARect := Owner.BoundsRect;
|
|
ARect.TopLeft := Owner.ClientToScreen(ARect.TopLeft);
|
|
ARect.BottomRight := Owner.ClientToScreen(ARect.BottomRight);
|
|
AForm.Top := (ARect.Top + ARect.Bottom - AForm.Height) shr 1;
|
|
AForm.Left := (ARect.Left + ARect.Right - AForm.Width) shr 1;
|
|
try
|
|
(AForm as TcxSSFormatDialog).Execute(ACells, Self);
|
|
finally
|
|
AForm.Free;
|
|
end;
|
|
finally
|
|
History.StopComplexAction;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.InsertCells(const ACells: TRect;
|
|
ACellsModify: TcxSSCellsModify);
|
|
begin
|
|
if Owner.ExcelProtectionStyle and not CanModify(Owner, Self, ACells) then Exit;
|
|
with Owner do
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
if ACellsModify in [msAllRow, msAllCol] then
|
|
FormulasCache.UpdateRef(FPages.IndexOf(Self), ACells, False, ACellsModify = msAllCol);
|
|
DataStorage.InsertCells(ACells, ACellsModify);
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.Invalidate;
|
|
begin
|
|
if not Owner.CaptionBar.Visible then
|
|
Owner.Invalidate
|
|
else
|
|
inherited Invalidate;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.Paste(const APlace: TPoint);
|
|
var
|
|
S: string;
|
|
AText: string;
|
|
APos, I: Integer;
|
|
ACol, ARow: Integer;
|
|
Action: TcxComplexAction;
|
|
ACanEdit: Boolean;
|
|
AChangedCells: TRect;
|
|
AreCellsChanged: Boolean;
|
|
|
|
begin
|
|
ACol := APlace.X;
|
|
ARow := APlace.Y;
|
|
if not CanModify(Owner, Self, ACol, ARow) then Exit;
|
|
ACanEdit := True;
|
|
Owner.Listener.OnEditing(Self, ACol, ARow, ACanEdit);
|
|
if not ACanEdit then Exit;
|
|
APos := 1;
|
|
TcxHistoryAccess(Owner.History).AddComplexAction(TcxComplexAction, cxGetResourceString(@scxPasteCommand), Action);
|
|
Owner.BeginUpdate;
|
|
AreCellsChanged := True;
|
|
try
|
|
try
|
|
if not Owner.SpreadSheetClipboardDataToData(Self, APlace.X, APlace.Y, AChangedCells) then
|
|
begin
|
|
AChangedCells := Rect(ACol, ARow, ACol - 1, ARow - 1);
|
|
S := cxSSClipBoard.DataAsUnicode;
|
|
if (Length(S) > 0) and (S[Length(S)] = #0) then
|
|
SetLength(S, Length(S) - 1);
|
|
AText := '';
|
|
AChangedCells.TopLeft := APlace;
|
|
while APos < Length(S) do
|
|
begin
|
|
I := APos;
|
|
while (I < Length(S)) and not dxCharInSet(S[I], [#9, #13, #10]) do Inc(I);
|
|
if I <> APos then
|
|
AText := System.Copy(S, APos, I - APos)
|
|
else
|
|
begin
|
|
if S[I] = #9 then
|
|
begin
|
|
Inc(ACol);
|
|
end
|
|
else
|
|
if S[I] = #13 then
|
|
begin
|
|
if (I < Length(S)) and (S[I + 1] = #10) then
|
|
Inc(I);
|
|
Inc(ARow);
|
|
ACol := APlace.X;
|
|
end;
|
|
Inc(I);
|
|
if I > Length(S) then Dec(ARow);
|
|
AText := '';
|
|
end;
|
|
if I <= Length(S) then
|
|
begin
|
|
if CanModify(Owner, Self, ACol, ARow) then
|
|
with GetCellObject(ACol, ARow) do
|
|
try
|
|
Text := AText;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
AChangedCells.Bottom := ARow;
|
|
APos := I;
|
|
AChangedCells.Right := Max(AChangedCells.Right, ACol);
|
|
end;
|
|
end;
|
|
except
|
|
on ESpreadSheetError do
|
|
begin
|
|
AreCellsChanged := False;
|
|
raise;
|
|
end
|
|
else
|
|
raise;
|
|
end;
|
|
finally
|
|
if Assigned(Owner.FOnEndEdit) then Owner.FOnEndEdit(Self);
|
|
if AreCellsChanged then
|
|
CellsChanged(AChangedCells);
|
|
Owner.EndUpdate;
|
|
Owner.UpdateControl;
|
|
if Action <> nil then
|
|
TcxHistoryAccess(Owner.History).StopComplexAction;
|
|
end;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetCellObject(ACol, ARow: Integer): TcxSSCellObject;
|
|
begin
|
|
Result := TcxSSCellObject(DataStorage.CreateAccessCellObject(ACol, ARow));
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SelectCell(const ACol, ARow: Integer;
|
|
OpenEditor: Boolean = False);
|
|
begin
|
|
if (CellEditor <> nil) and CellEditor.Visible then Exit;
|
|
DataStorage.Selection := Rect(ACol, ARow, ACol, ARow);
|
|
if OpenEditor then
|
|
begin
|
|
Owner.SetFocus;
|
|
if DoEditorActivate then
|
|
begin
|
|
CellEditor.SetFocus;
|
|
CellEditor.SetCursorPosition(Point(0, 0));
|
|
end;
|
|
end;
|
|
Invalidate;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetMergedState(const ARect: TRect; IsMerge: Boolean);
|
|
begin
|
|
if not CanModify(Owner, Self, ARect) then Exit;
|
|
Owner.BeginUpdate;
|
|
try
|
|
DataStorage.MergeUnMerge(ARect, IsMerge);
|
|
if IsMerge then
|
|
begin
|
|
with GetCellObject(ARect.Left, ARect.Top) do
|
|
try
|
|
if Text <> '' then
|
|
CheckCellWordBreak;
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
finally
|
|
Owner.EndUpdate;
|
|
{ if not Listener.IsLocked then
|
|
ViewInfo.UpdateViewInfo;}
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetVisibleState(const ARect: TRect;
|
|
ACols, ARows, AShow: Boolean);
|
|
var
|
|
I: Integer;
|
|
R: TRect;
|
|
begin
|
|
if (Owner.FCellEditor <> nil) and Owner.FCellEditor.Focused then
|
|
Owner.SetFocus;
|
|
Owner.BeginUpdate;
|
|
try
|
|
if ACols then
|
|
for I := ARect.Left to ARect.Right do
|
|
begin
|
|
DataStorage.Headers[htCol].Visible[I] := AShow;
|
|
if AShow and (DataStorage.Headers[htCol].Size[I] = 0) then
|
|
DataStorage.Headers[htCol].Size[I] :=
|
|
DataStorage.Headers[htCol].DefaultSize;
|
|
end;
|
|
if ARows then
|
|
for I := ARect.Top to ARect.Bottom do
|
|
begin
|
|
DataStorage.Headers[htRow].Visible[I] := AShow;
|
|
if AShow and (DataStorage.Headers[htRow].Size[I] = 0) then
|
|
DataStorage.Headers[htRow].Size[I] :=
|
|
DataStorage.Headers[htRow].DefaultSize;
|
|
end;
|
|
finally
|
|
if not AShow and EqualRect(ARect, SelectionRect) then
|
|
begin
|
|
R := ARect;
|
|
if ACols then
|
|
with TcxHeaderAccess(Cols) do
|
|
OffsetRect(R, GetNextItem(ARect.Left, True) - ARect.Left, 0);
|
|
if ARows then
|
|
with TcxHeaderAccess(Rows) do
|
|
OffsetRect(R, 0, GetNextItem(ARect.Top, True) - ARect.Top);
|
|
SelectionRect := R;
|
|
end;
|
|
Owner.EndUpdate;
|
|
Owner.UpdateControl;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.Sort(const ARect: TRect; const ASortTypes: array of TcxSortType);
|
|
var
|
|
Action: TcxComplexAction;
|
|
begin
|
|
TcxHistoryAccess(Owner.History).AddComplexAction(TcxComplexAction, cxGetResourceString(@scxSortCellsAction), Action);
|
|
try
|
|
Owner.BeginUpdate;
|
|
try
|
|
DataStorage.Sort(ARect, ASortTypes);
|
|
finally
|
|
Owner.EndUpdate;
|
|
end;
|
|
finally
|
|
if Action <> nil then
|
|
TcxHistoryAccess(Owner.History).StopComplexAction;
|
|
end;
|
|
end;
|
|
|
|
function TcxSSBookSheet.DoEditorActivate: Boolean;
|
|
var
|
|
ATopLeft: TPoint;
|
|
ARect: TRect;
|
|
I, J: Integer;
|
|
begin
|
|
if CellReadOnly(Owner, Self, DataStorage.Col, DataStorage.Row) then Exit;
|
|
Result := True;
|
|
Listener.OnEditing(Self, DataStorage.Col, DataStorage.Row, Result);
|
|
if not Result then Exit;
|
|
if CellEditor = nil then
|
|
begin
|
|
Owner.FCellEditor :=
|
|
Owner.GetInplaceEditClass.Create(Owner, True) as TcxSSInplaceTextEdit;
|
|
CellEditor.Parent := Owner;
|
|
CellEditor.OnEndEdit := OnEndEditCell;
|
|
end;
|
|
if DataStorage.Col < ViewInfo.LeftCol then
|
|
ViewInfo.LeftCol := DataStorage.Col;
|
|
if DataStorage.Row < ViewInfo.TopRow then
|
|
ViewInfo.TopRow := DataStorage.Row;
|
|
ATopLeft := TPoint(ViewInfo.TopLeft);
|
|
FEditingPos := Point(DataStorage.Col, DataStorage.Row);
|
|
ARect := DataStorage.CellRect(ATopLeft.X, ATopLeft.Y,
|
|
DataStorage.Col, DataStorage.Row, True);
|
|
with GetCellObject(DataStorage.Col, DataStorage.Row) do
|
|
try
|
|
Style.Font.AssignTo(CellEditor.Font);
|
|
if Style.Brush.BackgroundColor <= 55 then
|
|
CellEditor.Color := Self.Owner.Palette^[Style.Brush.BackgroundColor]
|
|
else
|
|
CellEditor.Color := Self.Owner.BackgroundColor;
|
|
finally
|
|
Free;
|
|
end;
|
|
with ViewInfo.InfoData do
|
|
for I := 0 to Length(Bricks) - 1 do
|
|
if Bricks[I, 0].Col >= DataStorage.Col then
|
|
begin
|
|
for J := 0 to Length(Bricks[0]) do
|
|
if Bricks[0, J].Row >= DataStorage.Row then
|
|
with Bricks[I, J] do
|
|
begin
|
|
if not IsMerge then
|
|
begin
|
|
ViewInfo.ClearBrickText(I, J);
|
|
CellEditor.AutoWidth := True;
|
|
CellEditor.MinimalWidth := Max(RectWidth(DisplayRect), RectWidth(TextRect)) - 5;
|
|
CellEditor.MinimalHeight := Max(RectHeight(DisplayRect), RectHeight(TextRect)) - 5;
|
|
ARect := Rect(TextRect.Left + 3, DisplayRect.Top, TextRect.Right, DisplayRect.Bottom + 2);
|
|
InflateRect(ARect, 0, -2);
|
|
end
|
|
else
|
|
begin
|
|
CellEditor.AutoWidth := True;
|
|
ARect := UnionBricks[UnionIndex].DisplayRect;
|
|
OffsetRect(ARect, 1, 1);
|
|
InflateRect(ARect, -3, -2);
|
|
CellEditor.MinimalWidth := RectWidth(ARect);
|
|
CellEditor.MinimalHeight := RectHeight(ARect);
|
|
end;
|
|
Dec(ARect.Bottom, 1);
|
|
Break;
|
|
end;
|
|
if ARect.Right < ViewInfo.RowHeaderWidth then
|
|
ARect.Right := ViewInfo.RowHeaderWidth;
|
|
if ARect.Top < ViewInfo.ColHeaderHeight then
|
|
ARect.Top := ViewInfo.ColHeaderHeight;
|
|
Break;
|
|
end;
|
|
CellEditor.SetBounds(ARect.Left - 2, ARect.Top, RectWidth(ARect), RectHeight(ARect));
|
|
CellEditor.InitEditor(DataStorage.CellText[Col, Row], DataStorage.CellText[Col, Row]);
|
|
FSheetState := [ssEditorActivate];
|
|
CellEditor.OnEndEdit := OnEndEditCell;
|
|
ViewInfo.UpdateOnChangeSelection;
|
|
end;
|
|
|
|
function TcxSSBookSheet.DoMouseWheel(Shift: TShiftState;
|
|
WheelDelta: Integer; MousePos: TPoint): Boolean;
|
|
begin
|
|
Owner.DeactivateEditor;
|
|
Result := True;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.ApplyAutoHeight(ARow: Integer);
|
|
|
|
function GetCellHeight(ACol: Integer): Integer;
|
|
var
|
|
I: Integer;
|
|
R, R1: TRect;
|
|
ACell: TcxSSCellRec;
|
|
ASettings: TcxTextParameters;
|
|
S: string;
|
|
begin
|
|
ACell := DataStorage.Cells[ACol, ARow];
|
|
Result := 0;
|
|
if ACell.DataType <> dtText then Exit;
|
|
R := ClientRect;
|
|
R.Right := R.Left;
|
|
if DataStorage.CheckInMergeRange(Point(ACol, ARow), R1) then
|
|
Exit;
|
|
with R1 do
|
|
for I := Left to Right do Inc(R.Right, Cols[I]);
|
|
InflateRect(R, -2, -2);
|
|
|
|
if (R.Right <= R.Left) or (ACell.Text = '') then Exit;
|
|
if Owner.FormulasCache.IsLoading or ACell.StylePtr^.WordBreak then
|
|
begin
|
|
Canvas.SelectFont(ACell.StylePtr^.FontPtr^.FontHandle);
|
|
Result := Canvas.TextHeight('Wg') + 2;
|
|
if not ACell.StylePtr^.WordBreak then Exit;
|
|
with ACell.StylePtr^ do
|
|
begin
|
|
S := OrdinalToFormatStr(ACell.Text, FormatIndex,
|
|
TcxCustomSpreadSheetBook(Owner).Precision);
|
|
Canvas.CalculateTextExtents(S, R, HorzAlign, VertAlign, WordBreak, ASettings);
|
|
end;
|
|
if (Length(ASettings.TextBricks) = 1) and (Rows.DefaultSize > Result) then
|
|
Result := Rows.DefaultSize
|
|
else
|
|
Result := Result * Length(ASettings.TextBricks);
|
|
end;
|
|
end;
|
|
|
|
var
|
|
I: Integer;
|
|
ASize: Integer;
|
|
begin
|
|
if Owner.IsDataLoading or not Owner.RowsAutoHeight {or not Rows.IsDefault[ARow]} then Exit;
|
|
ASize := 0;
|
|
for I := 0 to DataStorage.GetContentColCount do
|
|
ASize := Max(ASize, GetCellHeight(I));
|
|
if ASize <> 0 then
|
|
TcxHeaderAccess(Rows).SetScaledSize(ARow, ASize);
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.CellsChanged(const ARect: TRect);
|
|
var
|
|
I, J: Integer;
|
|
begin
|
|
for I := ARect.Left to ARect.Right do
|
|
for J := ARect.Top to ARect.Bottom do
|
|
if Assigned(Owner.OnCellChange) then Owner.OnCellChange(Self, I, J);
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.DblClick;
|
|
const
|
|
InactiveStates: TcxSSHitTestStates =
|
|
[htRowHeader, htResize, htUpperLeft, htColHeader];
|
|
var
|
|
AHitState: TcxSSHitTestStates;
|
|
ACol, ARow: Integer;
|
|
begin
|
|
AHitState := ViewInfo.HitTest(FMouseDownPos.X, FMouseDownPos.Y, ACol, ARow);
|
|
if InactiveStates * AHitState <> [] then Exit;
|
|
DoEditorActivate;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.FocusChanged;
|
|
begin
|
|
inherited;
|
|
if not (ssEditorActivate in FSheetState) then FSheetState := [];
|
|
if Owner.HideSelection then
|
|
ViewInfo.UpdateOnCancelMode;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.InitScrollBars;
|
|
|
|
procedure SetInfo(Kind: TScrollBarKind; MaxLine, Up, Down: Integer);
|
|
var
|
|
AMax: Integer;
|
|
begin
|
|
AMax := Max(MaxLine, Down);
|
|
if (AMax > MaxLine) and (Up > 0) then
|
|
Dec(AMax);
|
|
with Owner do
|
|
SetScrollBarInfo(Kind, 0, AMax, 1,
|
|
Down - Up, Up, ScrollersVisible[ScrollBars, Kind], True);
|
|
end;
|
|
|
|
begin
|
|
SetInfo(sbVertical, DataStorage.MaxRow, Corners.Top, Corners.Bottom);
|
|
SetInfo(sbHorizontal, DataStorage.MaxColumn, Corners.Left, Corners.Right);
|
|
Owner.VScrollbar.ApplyData;
|
|
Owner.HScrollbar.ApplyData;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.KeyDown(var Key: Word; Shift: TShiftState);
|
|
|
|
procedure ChangeCursorPos(AKey: Integer; AShift: TShiftState);
|
|
var
|
|
APos: TRect;
|
|
AOldPos: TPoint;
|
|
ARect: TRect;
|
|
|
|
begin
|
|
with DataStorage do
|
|
begin
|
|
if ssSelection in FSheetState then
|
|
begin
|
|
APos.TopLeft := FCurrentPos;
|
|
APos.BottomRight := FCurrentPos;
|
|
end
|
|
else
|
|
APos := Selection;
|
|
|
|
AOldPos := FCurrentPos;
|
|
case AKey of
|
|
VK_LEFT:
|
|
FCurrentPos.X :=
|
|
TcxHeaderAccess(Headers[htCol]).GetNextItem(APos.Left, False);
|
|
VK_UP:
|
|
FCurrentPos.Y :=
|
|
TcxHeaderAccess(Headers[htRow]).GetNextItem(APos.Top, False);
|
|
VK_RIGHT:
|
|
FCurrentPos.X :=
|
|
TcxHeaderAccess(Headers[htCol]).GetNextItem(APos.Right, True);
|
|
VK_DOWN:
|
|
FCurrentPos.Y :=
|
|
TcxHeaderAccess(Headers[htRow]).GetNextItem(APos.Bottom, True);
|
|
end;
|
|
if (ssSelection in FSheetState) then
|
|
begin
|
|
ARect := Selection;
|
|
case AKey of
|
|
VK_LEFT:
|
|
if AOldPos.X = ARect.Right then
|
|
begin
|
|
ARect.Left := AOldPos.X;
|
|
ARect := CheckSelectionRect(ARect);
|
|
if ARect.Left <> AOldPos.X then
|
|
FCurrentPos.X := ARect.Left - 1
|
|
end;
|
|
VK_UP:
|
|
if AOldPos.Y = ARect.Bottom then
|
|
begin
|
|
ARect.Top := AOldPos.Y;
|
|
ARect := CheckSelectionRect(ARect);
|
|
if ARect.Top <> AOldPos.Y then
|
|
FCurrentPos.Y := ARect.Top - 1
|
|
end;
|
|
VK_RIGHT:
|
|
begin
|
|
if AOldPos.X = ARect.Left then
|
|
ARect.Right := AOldPos.X
|
|
else
|
|
ARect.Left := AOldPos.X;
|
|
ARect := CheckSelectionRect(ARect);
|
|
if ARect.Right <> AOldPos.X then FCurrentPos.X := ARect.Right + 1
|
|
end;
|
|
VK_DOWN:
|
|
begin
|
|
if AOldPos.Y = ARect.Top then
|
|
ARect.Bottom := AOldPos.Y
|
|
else
|
|
ARect.Top := AOldPos.Y;
|
|
ARect := CheckSelectionRect(ARect);
|
|
if ARect.Bottom <> AOldPos.Y then FCurrentPos.Y := ARect.Bottom + 1
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function GetCorners: TRect;
|
|
begin
|
|
Result.TopLeft := TPoint(ViewInfo.TopLeft);
|
|
Result.BottomRight := TPoint(ViewInfo.BottomRight);
|
|
end;
|
|
|
|
procedure ValidateCorners(var ACorners: TRect; var APos: TPoint);
|
|
begin
|
|
if APos.X < ACorners.Left then
|
|
ViewInfo.LeftCol := APos.X
|
|
else
|
|
if FCurrentPos.X > ACorners.Right then
|
|
ViewInfo.RightCol := APos.X;
|
|
if APos.Y < ACorners.Top then
|
|
ViewInfo.TopRow := APos.Y
|
|
else
|
|
if APos.Y > ACorners.Bottom then
|
|
ViewInfo.BottomRow := APos.Y
|
|
end;
|
|
|
|
function IsUnusedKey: Boolean;
|
|
begin
|
|
Result := (ssAlt in Shift) and (DataStorage.SelectionState = ssMultiSelect) or
|
|
(Key = VK_APPS);
|
|
end;
|
|
|
|
var
|
|
ACorners: TRect;
|
|
AScrollsPos: TPoint;
|
|
|
|
begin
|
|
inherited KeyDown(Key, Shift);
|
|
if IsUnusedKey then
|
|
Exit;
|
|
if (Key = VK_F2) and (not ((ssShift in Shift) or (ssCtrl in Shift)
|
|
or CellReadOnly(Owner, Self, FEditingPos.X, FEditingPos.Y))) then
|
|
begin
|
|
if DoEditorActivate then
|
|
begin
|
|
CellEditor.SetFocus;
|
|
CellEditor.SetCursorPosition(Point(0, 0));
|
|
end;
|
|
Exit;
|
|
end;
|
|
if Key = VK_TAB then
|
|
begin
|
|
FSheetState := [];
|
|
if ssShift in Shift then
|
|
Key := VK_LEFT
|
|
else
|
|
Key := VK_RIGHT;
|
|
Shift := [];
|
|
end;
|
|
if not (ssShift in Shift) then
|
|
FCurrentPos := DataStorage.Selection.TopLeft;
|
|
if Key = VK_CONTROL then Exit;
|
|
ACorners := GetCorners;
|
|
with DataStorage do
|
|
begin
|
|
if SelectionState = ssCurrentSelect then FCurrentPos := Point(Col, Row);
|
|
if (Key = VK_SHIFT) or (not (ssSelection in FSheetState) and (ssShift in Shift)) then
|
|
begin
|
|
FStartSelection := Selection.TopLeft;
|
|
FCurrentPos := Selection.BottomRight;
|
|
FSheetState := [ssSelection];
|
|
end;
|
|
if Key = VK_SHIFT then Exit;
|
|
ValidateCorners(ACorners, FCurrentPos);
|
|
case Key of
|
|
VK_LEFT..VK_DOWN :
|
|
ChangeCursorPos(Key, Shift);
|
|
VK_PRIOR:
|
|
begin
|
|
ViewInfo.BottomRow := ACorners.Top;
|
|
FCurrentPos.Y := ViewInfo.TopRow;
|
|
ACorners := GetCorners;
|
|
end;
|
|
VK_NEXT:
|
|
begin
|
|
FCurrentPos.Y := Row - ACorners.Top;
|
|
ViewInfo.TopRow := ACorners.Bottom;
|
|
FCurrentPos.Y := ViewInfo.TopRow;
|
|
ACorners := GetCorners;
|
|
end;
|
|
VK_END:
|
|
if ssCtrl in Shift then
|
|
FCurrentPos := Point(MaxColumn, MaxRow);
|
|
VK_HOME:
|
|
begin
|
|
if ssCtrl in Shift then
|
|
FCurrentPos := Point(0, 0)
|
|
else
|
|
FCurrentPos.X := 0;
|
|
while not Cols.Visible[FCurrentPos.X] do Inc(FCurrentPos.X);
|
|
while not Rows.Visible[FCurrentPos.Y] do Inc(FCurrentPos.Y);
|
|
end;
|
|
VK_DELETE:
|
|
begin
|
|
if Shift = [ssShift] then
|
|
Copy(SelectionRect, True)
|
|
else
|
|
Self.ClearCells(DataStorage.Selection, ssCtrl in Shift);
|
|
end;
|
|
VK_RETURN:
|
|
FCurrentPos.Y := FCurrentPos.Y + 1;
|
|
VK_INSERT:
|
|
begin
|
|
if Shift = [ssShift] then
|
|
Paste(SelectionRect.TopLeft)
|
|
else
|
|
if Shift = [ssCtrl] then
|
|
Copy(SelectionRect, False);
|
|
end;
|
|
end;
|
|
ValidateCorners(ACorners, FCurrentPos);
|
|
if not (ssSelection in FSheetState) and (Key <> VK_Shift) then
|
|
with FCurrentPos do Selection := Rect(X, Y, X, Y)
|
|
else
|
|
Selection := Rect(FCurrentPos.X, FCurrentPos.Y,
|
|
FStartSelection.X, FStartSelection.Y);
|
|
end;
|
|
AScrollsPos := TPoint(ViewInfo.TopLeft);
|
|
if (Key = VK_PRIOR) or (Key = VK_NEXT) or (Key = VK_END) or (Key = VK_HOME) or
|
|
((Key >= VK_LEFT) or (Key <=VK_DOWN)) then
|
|
begin
|
|
Scroll(sbHorizontal, scPosition, AScrollsPos.X, False);
|
|
Scroll(sbVertical, scPosition, AScrollsPos.Y, False);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.KeyPress(var Key: Char);
|
|
begin
|
|
inherited KeyPress(Key);
|
|
if (Byte(Key) >= $21) and not CellReadOnly(Owner, Self, DataStorage.Col, DataStorage.Row) then
|
|
begin
|
|
if DoEditorActivate then
|
|
begin
|
|
CellEditor.Text := Key;
|
|
CellEditor.SetFocus;
|
|
CellEditor.SetCursorPosition(Point(1, 0));
|
|
end
|
|
else
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.KeyUp(var Key: Word; Shift: TShiftState);
|
|
begin
|
|
if Key = VK_SHIFT then FSheetState := [];
|
|
inherited;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|
X, Y: Integer);
|
|
var
|
|
ACol, ARow: Integer;
|
|
AHitState: TcxSSHitTestStates;
|
|
const
|
|
AResizeCursor: array[Boolean] of TCursor = (crVSplit, crHSplit);
|
|
AState: array[Boolean] of TcxSSSheetState = (ssRowHeader, ssColHeader);
|
|
begin
|
|
inherited MouseDown(Button, Shift, X, Y);
|
|
if ssEditorActivate in FSheetState then
|
|
begin
|
|
CellEditor.SetFocus;
|
|
CellEditor.SetCursorPosition(CellEditor.GetEditPos(X - CellEditor.Left, Y - CellEditor.Top));
|
|
FSheetState := [];
|
|
Exit;
|
|
end;
|
|
FMouseDownPos := Point(X, Y);
|
|
AHitState := ViewInfo.HitTest(X, Y, ACol, ARow);
|
|
if htResize in AHitState then
|
|
begin
|
|
if ACol < 0 then
|
|
begin
|
|
FResizeHeaderType := htRow;
|
|
FSizeIndex := ARow
|
|
end
|
|
else
|
|
begin
|
|
FResizeHeaderType := htCol;
|
|
FSizeIndex := ACol;
|
|
end;
|
|
FSheetState := [ssResize] + [AState[htColHeader in AHitState]];
|
|
FChangedSizeValue := DataStorage.Headers[FResizeHeaderType][FSizeIndex];
|
|
end
|
|
else
|
|
begin
|
|
if mbRight = Button then
|
|
if (ACol < 0) or (ARow < 0) or DataStorage.IsMultiSelection then
|
|
Listener.OnSheetPopupMenu(Self, ClientToScreen(X, Y))
|
|
else
|
|
begin
|
|
DataStorage.Selection := Rect(ACol, ARow, ACol, ARow);
|
|
FDownCellPos := Point(ACol, ARow);
|
|
Listener.OnSheetPopupMenu(Self, ClientToScreen(X, Y))
|
|
end;
|
|
if (htCell in AHitState) and not (Button = mbRight) then
|
|
begin
|
|
if Button = mbLeft then
|
|
FSheetState := [ssSelection];
|
|
DataStorage.Selection := Rect(ACol, ARow, ACol, ARow);
|
|
FDownCellPos := Point(ACol, ARow);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.MouseMove(Shift: TShiftState; X, Y: Integer);
|
|
|
|
procedure CheckNeedScrollContent;
|
|
var
|
|
ANeedViewInfoUpdate: Boolean;
|
|
|
|
procedure DoScroll(AKind: TScrollBarKind; ACode: TScrollCode; APos: Integer);
|
|
begin
|
|
if APos > 0 then
|
|
begin
|
|
Scroll(AKind, ACode, APos, False);
|
|
ANeedViewInfoUpdate := True;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
if Y < Owner.ColHeaderHeight then
|
|
DoScroll(sbVertical, scLineUp, ViewInfo.TopRow)
|
|
else
|
|
if Y > Height then
|
|
DoScroll(sbVertical, scLineDown, ViewInfo.BottomRow);
|
|
if X < Owner.RowHeaderWidth then
|
|
DoScroll(sbHorizontal, scLineUp, ViewInfo.LeftCol)
|
|
else
|
|
if X > Width then
|
|
DoScroll(sbHorizontal, scLineDown, ViewInfo.RightCol);
|
|
if ANeedViewInfoUpdate then
|
|
ViewInfo.TopLeft := Point(Owner.HScrollBar.Data.Position,
|
|
Owner.VScrollBar.Data.Position);
|
|
end;
|
|
|
|
var
|
|
ACol, ARow: Integer;
|
|
AHitState: TcxSSHitTestStates;
|
|
ASize: Integer;
|
|
AR, ACr: TRect;
|
|
|
|
const
|
|
AResizeCursor: array[Boolean] of TCursor = (crVSplit, crHSplit);
|
|
|
|
begin
|
|
inherited MouseMove(Shift, X, Y);
|
|
if ((ssLeft in Shift) or (ssRight in Shift)) and
|
|
not ((ssResize in FSheetState) or (ssSelection in FSheetState)) then Exit;
|
|
// if need scrolling
|
|
if (ssLeft in Shift) and not (ssResize in FSheetState) then
|
|
CheckNeedScrollContent;
|
|
//..........
|
|
if (ssSelection in FSheetState) and not ((ssLeft in Shift) or (ssRight in Shift)) then Exit;
|
|
AHitState := ViewInfo.HitTest(X, Y, ACol, ARow);
|
|
if (ssResize in FSheetState) and (ssLeft in Shift) then
|
|
begin
|
|
if FResizeHeaderType = htCol then
|
|
ASize := X - FMouseDownPos.X
|
|
else
|
|
ASize := Y - FMouseDownPos.Y;
|
|
ASize := ASize + FChangedSizeValue + 1;
|
|
if ASize < 0 then
|
|
ASize := 0;
|
|
DataStorage.Headers[FResizeHeaderType].Size[FSizeIndex] := ASize;
|
|
end
|
|
else
|
|
begin
|
|
if (htResize in AHitState) and not (ssSelection in FSheetState) then
|
|
begin
|
|
Cursor := AResizeCursor[htColHeader in AHitState];
|
|
if htColHeader in AHitState then
|
|
FSizeIndex := ACol
|
|
else
|
|
FSizeIndex := ARow;
|
|
end
|
|
else
|
|
begin
|
|
Cursor := crSSSelect;
|
|
if ssSelection in FSheetState then
|
|
begin
|
|
with ViewInfo.InfoData do
|
|
begin
|
|
if ACol < 0 then ACol := 0;
|
|
if ARow < 0 then ARow := 0;
|
|
end;
|
|
DataStorage.Selection := Rect(ACol, ARow, FDownCellPos.X, FDownCellPos.Y);
|
|
AR := DataStorage.Selection;
|
|
ACr.TopLeft := ViewInfo.TopLeft;
|
|
ACr.BottomRight := ViewInfo.BottomRight;
|
|
{ if (ARow > FDownCellPos.Y) then
|
|
begin
|
|
if (AR.Bottom - 1) >= ACr.Bottom then
|
|
ViewInfo.BottomRow := AR.Bottom;
|
|
end
|
|
else
|
|
if (ARow <= FDownCellPos.Y) then
|
|
begin
|
|
end; }
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
inherited;
|
|
if not (ssEditorActivate in FSheetState) then
|
|
begin
|
|
FSheetState := [];
|
|
Exit;
|
|
end
|
|
else
|
|
FSheetState := [];
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.OnEndEditCell(Sender: TObject);
|
|
begin
|
|
if Owner.HandleAllocated then
|
|
begin
|
|
try
|
|
FSheetState := [];
|
|
CellEditor.Visible := False;
|
|
with GetCellObject(FEditingPos.X, FEditingPos.Y) do
|
|
try
|
|
FIsEditMode := True;
|
|
Text := CellEditor.DisplayText;
|
|
finally
|
|
FIsEditMode := False;
|
|
Free;
|
|
end;
|
|
finally
|
|
ViewInfo.UpdateViewInfo;
|
|
if Assigned(Owner.FOnEndEdit) then
|
|
Owner.FOnEndEdit(Self);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.Paint;
|
|
begin
|
|
ViewInfo.InfoChanged := False;
|
|
Owner.Painter.Paint(Canvas, ViewInfo.InfoData);
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.Scroll(AScrollBarKind: TScrollBarKind; AScrollCode: TScrollCode;
|
|
var AScrollPos: Integer; IsViewInfoUpdate: Boolean = True);
|
|
var
|
|
AMax: Integer;
|
|
AUpPos: Integer;
|
|
ADown: Integer;
|
|
APageSize: Integer;
|
|
AScroller: TcxControlScrollBar;
|
|
begin
|
|
if AScrollCode = scEndScroll then Exit;
|
|
if AScrollBarKind = sbHorizontal then
|
|
begin
|
|
AScroller := Owner.HScrollBar;
|
|
AMax := Max(DataStorage.MaxColumn, ViewInfo.RightCol);
|
|
AUpPos := ViewInfo.LeftCol +
|
|
TcxHeaderAccess(DataStorage.Headers[htCol]).GetCountItems(ViewInfo.LeftCol,
|
|
Width - ViewInfo.RowHeaderWidth, False) + 1;
|
|
ADown:= FSheetViewInfo.RightCol;
|
|
APageSize := ViewInfo.RightCol - ViewInfo.LeftCol;
|
|
if FSheetViewInfo.RightCol = FSheetViewInfo.LeftCol then
|
|
begin
|
|
if AScrollCode = scPageUp then
|
|
Dec(AUpPos)
|
|
else
|
|
Inc(ADown);
|
|
Inc(APageSize);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
AScroller := Owner.VScrollBar;
|
|
AMax := Max(DataStorage.MaxRow, ViewInfo.BottomRow);
|
|
AUpPos := ViewInfo.TopRow +
|
|
TcxHeaderAccess(DataStorage.Headers[htRow]).GetCountItems(ViewInfo.TopRow,
|
|
Height - ViewInfo.ColHeaderHeight, False) + 1;
|
|
ADown:= FSheetViewInfo.BottomRow;
|
|
APageSize := ViewInfo.BottomRow - ViewInfo.TopRow;
|
|
if FSheetViewInfo.TopRow = FSheetViewInfo.BottomRow then
|
|
begin
|
|
Inc(ADown);
|
|
Inc(APageSize);
|
|
end;
|
|
end;
|
|
if AUpPos < 0 then AUpPos := 0;
|
|
with AScroller.Data do
|
|
begin
|
|
Position := AScroller.Position;
|
|
Max := AScroller.Max;
|
|
PageSize := APageSize;
|
|
case AScrollCode of
|
|
scLineUp :
|
|
Position :=
|
|
TcxHeaderAccess(DataStorage.Headers[TcxSSHeaderType(AScrollBarKind)]).GetNextItem(Position, False);
|
|
scLineDown:
|
|
Position :=
|
|
TcxHeaderAccess(DataStorage.Headers[TcxSSHeaderType(AScrollBarKind)]).GetNextItem(Position, True);
|
|
scPageDown:
|
|
Position := ADown;
|
|
scPageUp:
|
|
Position := AUpPos;
|
|
scPosition:
|
|
Position := AScrollPos;
|
|
end;
|
|
if Position < 0 then Position := 0;
|
|
if (Position + PageSize) > AMax then Max := Position + PageSize - 1;
|
|
if Max < 15 then Max := 15;
|
|
end;
|
|
if IsViewInfoUpdate then
|
|
case AScrollBarKind of
|
|
sbHorizontal:
|
|
begin
|
|
FSheetViewInfo.LeftCol := AScroller.Data.Position;
|
|
AScrollPos := FSheetViewInfo.LeftCol;
|
|
end;
|
|
sbVertical:
|
|
begin
|
|
FSheetViewInfo.TopRow := AScroller.Data.Position;
|
|
AScrollPos := FSheetViewInfo.TopRow;
|
|
end;
|
|
end;
|
|
// InitScrollBars;
|
|
// AScroller.ApplyData;
|
|
end;
|
|
|
|
function TcxSSBookSheet.ViewInfoValid: Boolean;
|
|
begin
|
|
Result := Visible and (ViewInfo <> nil) and
|
|
(Owner <> nil) and (Owner.ActiveSheet = Self);
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetActiveCell: TPoint;
|
|
begin
|
|
Result := DataStorage.Selection.TopLeft;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetCellEditor: TcxSSInplaceTextEdit;
|
|
begin
|
|
Result := Owner.FCellEditor;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetColHeader: TcxSSHeader;
|
|
begin
|
|
Result := DataStorage.Headers[htCol];
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetColumnCount: Integer;
|
|
begin
|
|
Result := DataStorage.MaxColumn;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetCorners: TRect;
|
|
begin
|
|
if ViewInfo <> nil then
|
|
begin
|
|
with ViewInfo do
|
|
begin
|
|
Result.TopLeft := TopLeft;
|
|
Result.BottomRight := BottomRight;
|
|
end;
|
|
end
|
|
else
|
|
Result := Rect(0, 0, 0, 0);
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetContentColCount: Integer;
|
|
begin
|
|
Result := DataStorage.GetContentColCount;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetContentRowCount: Integer;
|
|
begin
|
|
Result := DataStorage.GetContentRowCount;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetCurrentCol: Integer;
|
|
begin
|
|
Result := DataStorage.Col;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetCurrentRow: Integer;
|
|
begin
|
|
Result := DataStorage.Row;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetCell(const ACol, ARow: Integer): IcxSpreadSheetCell;
|
|
begin
|
|
Supports(TObject(GetCellObject(ACol, ARow)), IcxSpreadSheetCell, Result);
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetHistory: TcxSpreadSheetHistory;
|
|
begin
|
|
Result := Owner.History;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetIsLoaded: Boolean;
|
|
begin
|
|
Result := Owner.IsLoaded;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetListener: TcxSSListener;
|
|
begin
|
|
Result := (Owner as TcxCustomSpreadSheetBook).Listener;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetPageIndex: Integer;
|
|
begin
|
|
Result := Owner.FPages.IndexOf(Self);
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetSheetCaption: string;
|
|
begin
|
|
Result := DataStorage.SheetCaption;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetRowCount: Integer;
|
|
begin
|
|
Result := DataStorage.MaxRow;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetRowHeader: TcxSSHeader;
|
|
begin
|
|
Result := DataStorage.Headers[htRow];
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetSelectionRect: TRect;
|
|
begin
|
|
Result := DataStorage.Selection;
|
|
end;
|
|
|
|
function TcxSSBookSheet.GetTopLeft: TPoint;
|
|
begin
|
|
Result := ViewInfo.TopLeft;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetActiveCell(const Value: TPoint);
|
|
begin
|
|
DataStorage.Selection := Rect(Value.X, Value.Y, Value.X, Value.Y);
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetColRowSize(const AKind: TcxSSHeaderType;
|
|
const AColumn, ASize: Integer; ALocked: Boolean; AVisible: Boolean = True);
|
|
begin
|
|
with DataStorage.Headers[AKind] do
|
|
begin
|
|
Size[AColumn] := ASize;
|
|
LockProtect[AColumn] := ALocked;
|
|
Visible[AColumn] := AVisible;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetCorners(const Value: TRect);
|
|
begin
|
|
ViewInfo.TopLeft := Value.TopLeft;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetDefaultSize(const AKind: TcxSSHeaderType;
|
|
ASize: Integer);
|
|
begin
|
|
DataStorage.Headers[AKind].DefaultSize := ASize;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetMergedCells(const ARect: TRect; IsMerge: Boolean);
|
|
begin
|
|
SetMergedState(ARect, IsMerge);
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetPageDimension(const AHorzCount, AVertCount: Integer);
|
|
begin
|
|
DataStorage.Dimension := TSize(Point(AHorzCount + 1, AVertCount + 1));
|
|
DataStorage.SetCapacity(TSize(Point(AHorzCount, AVertCount)));
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetProtection(Value: Boolean);
|
|
begin
|
|
FProtected := Value;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetSheetCaption(Value: string);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Owner.Listener.OnChangeSheetCaption(Self, Value);
|
|
if DataStorage.SheetCaption <> Value then
|
|
begin
|
|
for I := 0 to Owner.PageCount - 1 do
|
|
if (Owner.Pages[I] <> Self) and (AnsiCompareText(Owner.Pages[I].DataStorage.SheetCaption, Value) = 0) then
|
|
raise ESpreadSheetError.Create(cxGetResourceString(@scxSpreadSheetInvalidSheetCaption));
|
|
DataStorage.SheetCaption := Value;
|
|
Owner.CaptionBar.ReCalcViewInfo;
|
|
Owner.UpdateControl;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetShowGrid(const Value: Boolean);
|
|
begin
|
|
if Value = FShowGrid then Exit;
|
|
FShowGrid := Value;
|
|
ViewInfo.UpdateViewInfo;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetShowHeaders(const Value: Boolean);
|
|
begin
|
|
if FShowHeaders = Value then Exit;
|
|
FShowHeaders := Value;
|
|
Owner.UpdateControl;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetShowFormulas(const Value: Boolean);
|
|
begin
|
|
if Value = FShowFormulas then Exit;
|
|
FShowFormulas := Value;
|
|
Owner.UpdateControl;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetSelectionRect(Value: TRect);
|
|
|
|
function GetActualSize(AItems: TcxSSHeader; AStart, AFinish: Integer): Integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := 0;
|
|
for I := AStart to AFinish do
|
|
begin
|
|
Inc(Result, AItems.Size[I]);
|
|
if Result <> 0 then Break;
|
|
end;
|
|
end;
|
|
|
|
var
|
|
ColsWidth, RowsHeight: Integer;
|
|
begin
|
|
repeat
|
|
ColsWidth := GetActualSize(Cols, Value.Left, Value.Right);
|
|
if ColsWidth = 0 then
|
|
begin
|
|
OffsetRect(Value, 1, 0);
|
|
ColsWidth := GetActualSize(Cols, Value.Left, Value.Right);
|
|
end;
|
|
RowsHeight := GetActualSize(Rows, Value.Top, Value.Bottom);
|
|
if RowsHeight = 0 then
|
|
begin
|
|
OffsetRect(Value, 0, 1);
|
|
RowsHeight := GetActualSize(Rows, Value.Top, Value.Bottom);
|
|
end;
|
|
until (ColsWidth <> 0) and (RowsHeight <> 0);
|
|
DataStorage.Selection := Value;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetTopLeft(const Value: TPoint);
|
|
begin
|
|
ViewInfo.TopLeft := Value;
|
|
end;
|
|
|
|
procedure TcxSSBookSheet.SetViewInformation(const ASelectionRect: TRect;
|
|
AViewFormulas, AViewGrid, AViewHeaders, AScrollBars: Boolean);
|
|
begin
|
|
FShowHeaders := AViewHeaders;
|
|
FShowGrid := AViewGrid;
|
|
FShowFormulas := AViewFormulas;
|
|
DataStorage.Selection := ASelectionRect;
|
|
Owner.UpdateControl;
|
|
end;
|
|
|
|
{ TcxSSListener }
|
|
constructor TcxSSListener.Create(AOwner: TcxCustomSpreadSheetBook);
|
|
begin
|
|
FOwner := AOwner;
|
|
FLockCount := 0;
|
|
end;
|
|
|
|
function TcxSSListener.BeginUpdate: Integer;
|
|
begin
|
|
Inc(FLockCount);
|
|
Result := FLockCount;
|
|
end;
|
|
|
|
function TcxSSListener.EndUpdate: Integer;
|
|
begin
|
|
if FLockCount > 0 then
|
|
Dec(FLockCount);
|
|
Result := FLockCount;
|
|
end;
|
|
|
|
function TcxSSListener.IsLocked: Boolean;
|
|
begin
|
|
Result := FLockCount > 0;
|
|
end;
|
|
|
|
procedure TcxSSListener.OnActiveCellChanging(Sender: TcxSSBookSheet;
|
|
const ActiveCell: TPoint; var CanSelect: Boolean);
|
|
begin
|
|
if IsLocked then Exit;
|
|
if Assigned(Owner.OnActiveCellChanging) then
|
|
Owner.OnActiveCellChanging(Sender, ActiveCell, CanSelect)
|
|
end;
|
|
|
|
procedure TcxSSListener.OnActiveSheetChanging(Sender: TcxCustomSpreadSheetBook;
|
|
const ActiveSheet: Integer; var CanSelect: Boolean);
|
|
begin
|
|
if IsLocked then Exit;
|
|
if Assigned(Owner.OnActiveSheetChanging) then
|
|
Owner.OnActiveSheetChanging(Sender, ActiveSheet, CanSelect);
|
|
end;
|
|
|
|
procedure TcxSSListener.OnChangeCellData(Sender: TcxSSBookSheet;
|
|
const ACol, ARow: Integer);
|
|
begin
|
|
if IsLocked then Exit;
|
|
if Sender.ViewInfoValid then
|
|
Sender.ViewInfo.UpdateCellInfo(ACol, ARow);
|
|
if Assigned(Owner.OnCellChange) then
|
|
Owner.OnCellChange(Sender, ACol, ARow);
|
|
end;
|
|
|
|
procedure TcxSSListener.OnChangeDefaultStyle(const AOldValue,
|
|
ANewValue: TcxSSCellStyleRec);
|
|
begin
|
|
if IsLocked then Exit;
|
|
if Owner.ViewInfoValid then
|
|
Owner.ActiveSheet.ViewInfo.UpdateViewInfo;
|
|
end;
|
|
|
|
procedure TcxSSListener.OnChangeLockColRow(Sender: TcxSSBookSheet;
|
|
AKind: TcxSSHeadertype; AIndex: Integer; AOldValue, ANewValue: Boolean);
|
|
begin
|
|
if IsLocked then Exit;
|
|
end;
|
|
|
|
procedure TcxSSListener.OnChangeSelection(Sender: TcxSSBookSheet;
|
|
const AOldValue, ANewValue: TRect);
|
|
begin
|
|
if IsLocked then Exit;
|
|
if Sender.ViewInfoValid then
|
|
Sender.ViewInfo.UpdateOnChangeSelection;
|
|
if Assigned(Owner.OnSetSelection) then
|
|
Owner.OnSetSelection(Owner, Sender);
|
|
end;
|
|
|
|
procedure TcxSSListener.OnChangeSheetCaption(Sender: TcxSSBookSheet;
|
|
var ACaption: string);
|
|
begin
|
|
Owner.SetModified;
|
|
if IsLocked then Exit;
|
|
if Assigned(Owner.OnChangeSheetCaption) then
|
|
Owner.OnChangeSheetCaption(Sender, ACaption);
|
|
end;
|
|
|
|
procedure TcxSSListener.OnChangeSizeColRow(Sender: TcxSSBookSheet;
|
|
AKind: TcxSSHeaderType; AIndex: Integer; var ANewSize: TcxSSSize);
|
|
begin
|
|
with Owner do
|
|
begin
|
|
if (AKind = htCol) and Assigned(OnResizeCol) then
|
|
OnResizeCol(Sender, AIndex, ANewSize)
|
|
else
|
|
if (AKind = htRow) and Assigned(OnResizeRow) then
|
|
OnResizeRow(Sender, AIndex, ANewSize);
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSListener.OnChangeVisibleColRow(Sender: TcxSSBookSheet;
|
|
AKind: TcxSSHeaderType; AIndex: Integer; AOldValue, ANewValue: Boolean);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
with Sender, SelectionRect do
|
|
begin
|
|
if (AKind = htRow) and ((AIndex >= Top) or (AIndex <= Bottom)) and not ANewValue then
|
|
begin
|
|
I := AIndex + 1;
|
|
while not Sender.Rows.Visible[I] do Inc(I);
|
|
SelectionRect := Rect(Left, I, Right, I);
|
|
end;
|
|
end;
|
|
if AKind = htCol then
|
|
begin
|
|
if Assigned(Owner.OnChangeColVisible) then
|
|
Owner.OnChangeColVisible(Owner, Sender, AIndex, AOldValue, ANewValue)
|
|
end
|
|
else
|
|
begin
|
|
if Assigned(Owner.OnChangeRowVisible) then
|
|
Owner.OnChangeRowVisible(Owner, Sender, AIndex, AOldValue, ANewValue);
|
|
end;
|
|
if IsLocked then Exit;
|
|
if Sender.ViewInfoValid then
|
|
Sender.ViewInfo.UpdateViewInfo;
|
|
end;
|
|
|
|
procedure TcxSSListener.OnClearCells(Sender: TcxSSBookSheet; const ACellRec: TRect;
|
|
var AUseDefaultStyle, CanClear: Boolean);
|
|
begin
|
|
if Assigned(Owner.OnClearCells) then
|
|
Owner.OnClearCells(Sender, ACellRec, AUseDefaultStyle, CanClear);
|
|
end;
|
|
|
|
procedure TcxSSListener.OnEditing(Sender: TcxSSBookSheet;
|
|
const ACol, ARow: Integer; var CanEdit: Boolean);
|
|
begin
|
|
if IsLocked then Exit;
|
|
if Assigned(FOwner.OnEditing) then
|
|
FOwner.OnEditing(Sender, ACol, ARow, CanEdit);
|
|
end;
|
|
|
|
procedure TcxSSListener.OnDeleteCells(Sender: TcxSSBookSheet; ACellRect: TRect;
|
|
AModifyType: TcxSSModifyType);
|
|
begin
|
|
if IsLocked then Exit;
|
|
end;
|
|
|
|
procedure TcxSSListener.OnHistoryChanged(Sender: TObject);
|
|
begin
|
|
if IsLocked then Exit;
|
|
if Assigned(Owner.OnHistoryChanged) then
|
|
Owner.OnHistoryChanged(Owner);
|
|
end;
|
|
|
|
procedure TcxSSListener.OnInsertCells(Sender: TcxSSBookSheet;
|
|
ACellRect: TRect; AModifyType: TcxSSModifyType);
|
|
begin
|
|
if IsLocked then Exit;
|
|
end;
|
|
|
|
procedure TcxSSListener.OnMergeCells(Sender: TcxSSBookSheet;
|
|
ACellRect: TRect; AIsMerge: Boolean; var CanMerge: Boolean);
|
|
begin
|
|
if IsLocked then Exit;
|
|
if Assigned(Owner.OnMergeCells) then
|
|
Owner.OnMergeCells(Sender, ACellRect, AIsMerge, CanMerge);
|
|
end;
|
|
|
|
procedure TcxSSListener.OnSheetPopupMenu(Sender: TcxSSBookSheet;
|
|
const AHitPoint: TPoint);
|
|
begin
|
|
try
|
|
if Assigned(Owner.OnContextPopup) then
|
|
Owner.OnContextPopup(Owner, AHitPoint, Owner.FContextPopupHandled);
|
|
if Owner.FContextPopupHandled or Assigned(Owner.PopupMenu) then Exit;
|
|
if Assigned(Owner.OnSheetPopupMenu) then
|
|
Owner.OnSheetPopupMenu(Sender, AHitPoint.X, AHitPoint.Y);
|
|
finally
|
|
Owner.FContextPopupHandled := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSListener.OnCaptionPopupMenu(Sender: TcxSSBookSheet;
|
|
const AHitPoint: TPoint);
|
|
begin
|
|
try
|
|
if Assigned(Owner.OnContextPopup) then
|
|
Owner.OnContextPopup(Owner, AHitPoint, Owner.FContextPopupHandled);
|
|
if Owner.FContextPopupHandled or Assigned(Owner.PopupMenu) then Exit;
|
|
if Assigned(Owner.OnCaptionPopupMenu) then
|
|
Owner.OnCaptionPopupMenu(Sender, AHitPoint.X, AHitPoint.Y);
|
|
finally
|
|
Owner.FContextPopupHandled := False;
|
|
end;
|
|
end;
|
|
|
|
procedure TcxSSListener.OnTopLeftChanging(Sender: TcxSSBookSheet;
|
|
var ATopLeft: TPoint);
|
|
begin
|
|
if Assigned(Owner.OnTopLeftChanging) then
|
|
Owner.OnTopLeftChanging(Sender, ATopLeft);
|
|
end;
|
|
|
|
procedure TcxSSListener.OnProgress(Sender: TObject; APercent: Byte);
|
|
begin
|
|
if Assigned(Owner.OnProgress) then
|
|
Owner.OnProgress(Owner, APercent);
|
|
end;
|
|
|
|
procedure TcxSSListener.OnResizeDataLength(Sender: TcxSSBookSheet;
|
|
AType: TcxSSHeaderType);
|
|
begin
|
|
if IsLocked then Exit;
|
|
end;
|
|
|
|
procedure TcxSSListener.UpdateAfterChanged(Sender: TcxSSBookSheet; ACellRect: TRect);
|
|
begin
|
|
if IsLocked then Exit;
|
|
Owner.DoRecalc;
|
|
if Sender.ViewInfoValid then
|
|
Sender.ViewInfo.UpdateCellsInfo(ACellRect);
|
|
end;
|
|
|
|
initialization
|
|
CF_ESSDATA := RegisterClipboardFormat(SCF_ESSCLIPBOARDFORMAT);
|
|
if IsWinNT then
|
|
CurrencyString := GetLocaleStrW(GetThreadLocale, LOCALE_SCURRENCY);
|
|
cxSSClipboard := TcxSSClipboard.Create;
|
|
if Screen.Cursors[crSSSelect] = Screen.Cursors[crDefault] then
|
|
Screen.Cursors[crSSSelect] := LoadCursor(HInstance, 'CR_SELECT');
|
|
if IsWinNT then
|
|
CurrencyString := GetLocaleStrW(GetThreadLocale, LOCALE_SCURRENCY);
|
|
cxHScrollHeight := GetSystemMetrics(SM_CYHSCROLL);
|
|
cxVScrollWidth := GetSystemMetrics(SM_CXVSCROLL);
|
|
|
|
finalization
|
|
cxSSClipboard.Free;
|
|
|
|
end.
|