I am a bit confused on how to change the color of a cell, for Font.ColorIndex, FillPattern.FgColorIndex, and FillPattern.BgColorIndex.
I am assuming that I somehow need to add the color to the ColorPalette and then select that index, but do not see how that is done.
Using FlexCel v3 on D2009.
Hi,
You know more about Excel than Microsoft does!! :)
This works perfectly for what I need. I also figured out that changing the fill color to "None" requires a TFlxPatternStyle_None (changing from Solid).
Also, your FlexCel_XlsAdapter.TXLSFile is working perfectly without any hiccups. I have controls for changing fonts, point sizes, bold, italics, underline, text alignment, font color and cell color. It copies cells, cell formulas, and cell formats.
I do have a question about copying formulas. (I think you already know what I am going to ask!) If I copy a cell that has the formula =$b5+c5 and paste it one cell to the right, it would be great if the formula changed to =$b5+d5. Do you have any special copy and paste procedures for formulas?
(This also opens a huge can of worms for inserting and deleting columns and rows.)
Sorry to be such a pain!
Rick
Hi,
procedure CopyRange(const stream: TMemoryStream;
const range: VCL_FlexCel_Core.TXlsCellRange;
const destRow, destCol: integer);
var
xls: FlexCel_XlsAdapter.TXlsFile;
begin
xls := FlexCel_XlsAdapter.TXlsFile.Create();
try
stream.Position := 0;
xls.Open(stream);
xls.InsertAndCopyRange(range, destRow, destCol, 1, TFlxInsertMode_ShiftRangeDown, TRangeCopyMode_All);
stream.Clear;
xls.Save(stream);
stream.Position := 0;
finally
xls.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ms: TMemoryStream;
range: VCL_FlexCel_Core.TXlsCellRange;
begin
FlexCelImport1.OpenFile('r:\test.xls');
ms := TMemoryStream.Create;
try
FlexCelImport1.SaveToStream(ms);
range.Left := 1;
range.Top := 1;
range.Bottom := 19;
range.Right := 15;
CopyRange(ms, range, 20, 20);
FlexCelImport1.LoadFromStream(ms);
finally
ms.Free;
end;
FlexCelImport1.Save('r:\newtest.xls');
end;
Again, I appreciate the DLL and help. You have excellent customer service! I have already compiled the 6617.zip file and will be testing it later today or tomorrow. I'll let you know how it goes.
Where are TFlxInsertMode_ShiftRangeDown and TRangeCopyMode_All declared?
Sorry, forgot to mention it `(and I was going to). Just add FlexCelDynEnums to the uses clauses. In older delphi versions enum aren't scoped, so you can't declare them in FlexCel_Core as FlexCel 6 does. You need to use the unit with the enums directly.
I am struggling with the InsertAndCopyRange. Nothing is happening.
I copied your CopyRange procedure and changed the TFlxInsertMode_ShiftRangeDown to TFlxInsertMode_NoneDown so that it would overwrite cells.
I am assuming that if I wanted to copy cell A3, that:
Top = 3
Bottom = 3
Left = 1
Right = 1
I then save the stream, issue the CopyRange(ms, range, 4, 1) to copy A3 to A4, and LoadFromStream. To get it back on the FlexCelGrid, I issue a recalculate (which does a savetostream, recalc, loadfromstream, and finally a LoadSheet). -- Note: I have also tried simply to do a grid.loadsheet right after the loadfromstream and that did nothing as well.
I thought that maybe I
was not linking in the right DCU files, but my Delphi library is
pointing to the v6617 folder. Then I remembered that the FlexCelDyn.dll
needed to be copied to the folder I am running from. However, the v6617
FlexCelDyn.dll has the same date as the v6611 FlexCelDyn.dll. Could that
be the problem?
Hi,
I just downloaded again and on one PC, it sees the DLL dated 2/19 and on another it sees 2/28. WEIRD. I re-extracted from the PC that sees it correctly and then compiled it.
What is the size of the FlexCelDyn.dll file? The one I have is 5523k dated 2/28/2015 3:47pm.
I am still getting nothing after all of that. Perhaps my code is wrong....but it looks like yours. I have separate copy and paste buttons.
I will copy in the routines. Before you go through them, please understand that I am an old-school programmer and code things differently than others. My variables are prefixed as:
W_ : Function or routine variable only
L_ : Private (local) variable for the unit
X_ : Function or routine passed-in variable
EF : These are fields from the Form. Most likely, TEdit fields. EFCellValue gets filled by the SelectCell method. It contains the value or formula of the current selected cell.
My copy routine is:
procedure TFrameXPayoff2.SBXCopyCellClick(Sender: TObject);
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Copy}
var
W_Value : TXlsCellValue;
begin
L_CopyFromRow := L_XLSRec.Row; // L_XLSRec is a record that contains info for the selected cell
L_CopyFromCol := L_XLSRec.Col;
W_Value := FlexCelImportPO.Cell[L_XLSRec.Row,L_XLSRec.Col];
If W_Value.IsFormula
then begin
L_Fmla := FlexCelImportPO.CellFormula[L_XLSRec.Row,L_XLSRec.Col];
EFCellValue.SelectAll; // If I can get the InsertAndCopyRange to work, some of this code will be deleted
EFCellValue.CopyToClipboard;
end
else begin
L_Fmla := '';
FlexCelGridPO.CopyToClipboard;
end;
SBXCopyCellFmtClick(Sender); // SBXCopyCellFmt is a speedbutton that simply copies the format
If Sender = SBXCutCell then begin // If I am cutting the cell, this clears the cell
FlexCelImportPO.CellValue[L_XLSRec.Row,L_XLSRec.Col] := '';
FlexCelImportPO.CellFormat[L_XLSRec.Row,L_XLSRec.Col] := 0;
SBXRecalcGridClick(Sender); // This does a recalc to freshen the grid after the cut
end;
end;
Essentially, what I am looking for in the copy are the row and col of the cell that is to be copied. Those are in the L_CopyFrom... variables. (I am waiting to see what exactly gets copied from the new InsertAndCopyRange before I simplify the Copy procedure.)
My paste routine looks like this:
procedure TFrameXPayoff2.SBXPasteCellClick(Sender: TObject);
{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Paste}
var
W_MS : TMemoryStream;
W_Range : VCL_FlexCel_Core.TXlsCellRange;
begin
If L_Fmla = ''
then FlexCelGridPO.PasteFromClipboard
else begin
W_MS := TMemoryStream.Create;
try
FlexCelImportPO.SaveToStream(W_MS);
W_Range.Left := L_CopyFromCol;
W_Range.Right := L_CopyFromCol;
W_Range.Top := L_CopyFromRow;
W_Range.Bottom := L_CopyFromRow;
CopyRange(W_MS,W_Range,L_XLSRec.Row,L_XLSRec.Col);
FlexCelImportPO.LoadFromStream(W_MS);
finally
W_MS.Free;
end;
end;
{ Eventually, this will be uncommented in order to copy the format as well (if needed)
SBXPasteCellFmtClick(Sender);
}
SBXRecalcGridClick(Sender);
end;
Here is CopyRange:
procedure TFrameXPayoff2.CopyRange(const stream: TMemoryStream;
const range: VCL_FlexCel_Core.TXlsCellRange;
const destRow, destCol: integer);
{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Copies a cell range}
var
xls: FlexCel_XlsAdapter.TXlsFile;
begin
xls := FlexCel_XlsAdapter.TXlsFile.Create();
try
stream.Position := 0;
xls.Open(stream);
xls.InsertAndCopyRange(range, destRow, destCol, 1, TFlxInsertMode_NoneDown, TRangeCopyMode_All);
stream.Clear;
xls.Save(stream);
stream.Position := 0;
finally
xls.Free;
end;
end;
As you can see, this is your code verbatim. Here is the grid recalc:
procedure TFrameXPayoff2.SBXRecalcGridClick(Sender: TObject);
{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Recalculate the grid}
var
W_Col : Integer;
W_Row : Integer;
W_MS : TMemoryStream;
begin
L_ProcessCellChange := False; // This temporarily disables the setting of the row and col in my SelectCell routine
W_Row := L_XLSRec.Row;
W_Col := L_XLSRec.Col;
W_MS := TMemoryStream.Create;
Try
FlexCelImportPO.SaveToStream(W_MS);
RecalcXLS(W_MS);
FlexCelImportPO.LoadFromStream(W_MS);
FlexCelGridPO.LoadSheet;
FlexCelGridPO.Row := W_Row;
FlexCelGridPO.Col := W_Col;
Finally
W_MS.Free;
End;
L_ProcessCellChange := True;
end;
And finally. RecalcXLS:
procedure TFrameXPayoff2.RecalcXLS(Const X_Stream: TMemoryStream);
{ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Recalculate the grid}
var
W_XLS : FlexCel_XlsAdapter.TXLSFile;
begin
W_XLS := FlexCel_XlsAdapter.TXlsFile.Create();
Try
X_Stream.Position := 0;
W_XLS.Open(X_Stream);
W_XLS.Recalc(True);
X_Stream.Clear;
W_XLS.Save(X_Stream);
X_Stream.Position := 0;
Finally
W_XLS.Free;
End;
end;
Hi,
Nope. Nothing got copied. The resulting newtest.xls is identical to the test.xls.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, VCL_FlexCel_Core, FlexCel_XLSAdapter, FlexCelDynEnums,
UExcelAdapter, XLSAdapter, UFlexCelImport;
type
TForm1 = class(TForm)
FlexCelImport1: TFlexCelImport;
XLSAdapter1: TXLSAdapter;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure CopyRange(const stream: TMemoryStream;
const range: VCL_FlexCel_Core.TXlsCellRange;
const destRow, destCol: integer);
var
xls: FlexCel_XlsAdapter.TXlsFile;
begin
xls := FlexCel_XlsAdapter.TXlsFile.Create();
try
stream.Position := 0;
xls.Open(stream);
xls.InsertAndCopyRange(range, destRow, destCol, 1, TFlxInsertMode_ShiftRangeDown, TRangeCopyMode_All);
stream.Clear;
xls.Save(stream);
stream.Position := 0;
finally
xls.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ms: TMemoryStream;
range: VCL_FlexCel_Core.TXlsCellRange;
begin
FlexCelImport1.OpenFile('N:\D2009Projects\Test\FlexCel\test.xls');
ms := TMemoryStream.Create;
try
FlexCelImport1.SaveToStream(ms);
range.Left := 1;
range.Top := 1;
range.Bottom := 19;
range.Right := 15;
CopyRange(ms, range, 20, 1);
FlexCelImport1.LoadFromStream(ms);
finally
ms.Free;
end;
FlexCelImport1.Save('N:\D2009Projects\Test\FlexCel\newtest.xls');
end;
end.
The only thing I added were the items in the Uses at the top. I also revised the XLS test and newtest files. Other than that, it should have worked.
So, that tells me there is something wrong on my PC. I am suspicious that the DLL is not the right one. If you want, you can email it directly to me as an attachment.
I've sent you en email with the test, let me know how it goes.
All is well! I thought I had altered my Library list to the updated routines and I had not. Thank you again for your excellent support!