| View previous topic :: View next topic |
| Author |
Message |
bitfarmer General User

Joined: 06 May 2004 Posts: 36 Location: Murcia, Spain
|
Posted: Fri May 14, 2004 3:54 am Post subject: Delphi: Interact with Calc docs from OpenOffice or Excel |
|
|
I had to make a non visual delphi object capable of interacting with spread sheets in general, first it was able to use Excel docs only, but now I have made it dual, so you can manage OpenOffice Calc docs or Excel docs transparently.
The code it self contains a example of use and a to-do list, as long as I improve it I will edit this post to reflect the new capabilities.
Hope it help to all delphi programers trying to master OpenOffice, it was dificult to work all this out without decent examples!
UPDATED: V0.95 (10-2009) with changes by Romulo merged with my own ones.
NOTE: This version works OK with OOo up to V3.1
BitFarmer.
| Code: |
// ********************************************
// ** Object for dual SpreadSheet managing **
// ** using Excel or OpenOffice automaticaly **
// ** By: Sergio Hernandez **
// ** oficina(at)hcsoft.net, CopyLeft 2009 **
// ** Version 0.96 20-01-2010 (DDMMYYYY) **
// ** Use it freely, change it, etc. **
// ********************************************
{EXAMPLE OF USE
//Create object: We have two flavours:
//(A) from an existing file...
HCalc:= THojaCalc.create(OpenDialog.FileName, false);
//(B) from a blank document...
HCalc:= THojaCalc.create(thcOpenOffice, true); //OpenOffice doc if possible, please
HCalc.FileName:= 'C:\MyNewDoc'; //Needs a file name before you SaveDoc!
//--end of creation.
HCalc.ActivateSheetByIndex(2); //Activate second sheet
if HCalc.IsActiveSheetProtected then
ShowMessage('2nd sheet of name "'+HCalc.ActiveSheetName+'" IS protected');
//Change a cell value (well, change formula, not the double float value)
if HCalc.CellText[i,2] = '' then HCalc.CellText[i,2] := 'Hello world!';
HCalc.AddNewSheet('New Sheet');
HCalc.PrintDoc;
HCalc.SaveDoc;
HCalc.Free;
}
{TODO LIST:
-PrintActiveSheet is not working for OpenOffice (is it even possible?)
-A way to write a date in a cell changing also the format (Excel is herratic in that)
-Listener for OpenOffice so I can be noticed if user visually close the doc.
}
{CHANGE LOG:
V0.96:
-Added PrintSheetsUntil(LastSheetName: string) -only works on excel- to print
out all tabs from 1 until -excluded- the one with the given name in such a
way that only one print job is created instead of one per tab (only way to do
this in previous versions, so converting part of a excel to a single PDF
using a printer like PDFCreator was not posible).
V0.95:
-ActivateSheetByIndex detect imposible index and allows to insert sheet 100 (it will create all necesary sheets)
-SaveDocAs added a second optional parameter for OOo to use Excel97 format (rescued from V0.93 by Rômulo)
-A little stronger ValidateSheetName() (filter away \ and " too).
V0.94:
-OpenOffice V2 compatible (small changes)
-A lot of "try except" to avoid silly errors.
-SaveDocAs(Name: string): boolean; (Added by Massimiliano Gozzi)
-New function FileName2URL(Name) to convert from FileName to URL (OOo SaveDosAs)
-New function ooCreateValue to hide all internals of OOo params creation
V0.93:
***************************
** By Rômulo Silva Ramos **
***************************
-FontSize(Row, Col, Size): change font size in that cell.
-BackgroundColor(row, col: integer; color:TColor);
-Add ValidateSheetName to validate sheet names when adding or renaming a sheet
REVERTED FUNCTIONS (not neccesary in newer version V0.95 anymore)
-Change AddNewSheet to add a new sheet in end at sheet list
*REVERTED IN V0.95*
It creates sheet following the active one, so to add at the end:
ActivateSheetByIndex(CountSheets);
AddNewSheet('Sheet '+IntToStr(CountSheets+1));
-Change in SaveDoc to use SaveAs/StoreAsUrl
*REVERTED V0.95*
Use SaveDocAs(Name, true) for StoreAsUrl in Excel97 format.
V0.92:
-SetActiveSheetName didn't change the name to the right sheet on OpenOffice.
-PrintPreview: New procedure to show up the print preview window.
-Bold(Row, Col): Make bold the text in that cell.
-ColumnWidth(col, width): To change a column width.
V0.91:
-NewDoc: New procedure for creating a blank doc (used in create)
-Create from empty doc adds a blank document and take visibility as parameter.
-New functions ooCreateValue and ooDispatch to clean up the code.
-ActiveSheetName: Now is a read-write property, not a read-only function.
-Visible: Now is a read-write property instead of a create param only.
V0.9:
-Create from empty doc now tries both programs (if OO fails try to use Excel).
-CellTextByName: Didn't work on Excel docs.
}
unit UHojaCalc;
interface
uses Variants, SysUtils, ComObj, Classes, Graphics;
//thcError: Tried to open but both failes
//thcNone: Haven't tried still to open any
type TTipoHojaCalc = (thcError, thcNone, thcExcel, thcOpenOffice);
type THojaCalc = class(TObject)
private
fVisible: boolean;
//Program loaded stuff...
procedure LoadProg;
procedure CloseProg;
function GetProgLoaded: boolean;
procedure NewDoc;
procedure LoadDoc;
procedure CloseDoc;
function GetDocLoaded: boolean;
function GetIsExcel: boolean;
function GetIsOpenOffice: boolean;
procedure SetVisible(v: boolean);
//Sheets stuff..
function GetCountSheets: integer;
function GetActiveSheetName: string;
procedure SetActiveSheetName(NewName: string);
//Cells stuff...
function GetCellText(row,col: integer): string;
procedure SetCellText(row,col: integer; Txt: string);
function GetCellTextByName(Range: string): string;
procedure SetCellTextByName(Range: string; Txt: string);
//OpenOffice only stuff...
function FileName2URL(FileName: string): string;
procedure ooDispatch(ooCommand: string; ooParams: variant);
function ooCreateValue(ooName: string; ooData: variant): variant;
//Aux functions
function ValidateSheetName(Name:string): string;
public
Tipo: TTipoHojaCalc; //Witch program was used to manage the doc?
FileName: string; //In windows FileName format C:\MyDoc.XXX
Programa: variant; //Excel or OpenOfice instance created.
DeskTop: variant; //OpenOffice desktop reference (not used now).
Document: variant; //Document opened.
ActiveSheet: variant; //Active sheet.
//Object internals...
constructor Create(Name: string; MakeVisible: boolean); overload;
constructor Create(MyTipo: TTipoHojaCalc; MakeVisible: boolean); overload;
destructor Destroy; override;
//Program loaded stuff...
function SaveDoc: boolean;
function SaveDocAs(Name: string; AsExcel97: boolean = false): boolean;
function PrintDoc: boolean;
procedure ShowPrintPreview;
property ProgLoaded: boolean read GetProgLoaded;
property DocLoaded: boolean read GetDocLoaded;
property IsExcel: boolean read GetIsExcel;
property IsOpenOffice: boolean read GetIsOpenOffice;
property Visible: boolean read fVisible write SetVisible;
//Sheets stuff...
function ActivateSheetByIndex(nIndex: integer): boolean;
function ActivateSheetByName(SheetName: string; CaseSensitive: boolean): boolean;
function IsActiveSheetProtected: boolean;
function PrintActiveSheet: boolean;
function PrintSheetsUntil(LastSheetName: string): boolean;
procedure AddNewSheet(NewName: string);
property CountSheets: integer read GetCountSheets;
property ActiveSheetName: string read GetActiveSheetName write SetActiveSheetName;
//Cells stuff...
procedure Bold(row,col: integer);
procedure BackgroundColor(row, col: integer; color: TColor);
procedure FontSize(row, col, size: integer);
procedure ColumnWidth(col, width: integer); //Width in 1/100 of mm.
property CellText[f,c: integer]: string read GetCellText write SetCellText;
property CellTextByName[Range: string]: string read GetCellTextByName write SetCellTextByName;
end;
implementation
// ************************
// ** Create and destroy **
// ************************
//Create with an empty doc of requested type (use thcExcel or thcOpenOffice)
//Remember to define FileName before calling to SaveDoc
constructor THojaCalc.Create(MyTipo: TTipoHojaCalc; MakeVisible: boolean);
var
i: integer;
IsFirstTry: boolean;
begin
//Close all opened things first...
CloseDoc;
CloseProg;
//I will try to open twice, so if Excel fails, OpenOffice is used instead
IsFirstTry:= true;
for i:= 1 to 2 do begin
//Try to open OpenOffice...
if (MyTipo = thcOpenOffice) or (MyTipo = thcNone)then begin
try
Programa:= CreateOleObject('com.sun.star.ServiceManager');
except
end;
if ProgLoaded then begin
Tipo:= thcOpenOffice;
break;
end else begin
if IsFirstTry then begin
//Try Excel as my second choice
MyTipo:= thcExcel;
IsFirstTry:= false;
end else begin
//Both failed!
break;
end;
end;
end;
//Try to open Excel...
if (MyTipo = thcExcel) or (MyTipo = thcNone) then begin
try
Programa:= CreateOleObject('Excel.Application');
except
end;
if ProgLoaded then begin
Tipo:= thcExcel;
break;
end else begin
if IsFirstTry then begin
//Try OpenOffice as my second choice
MyTipo:= thcOpenOffice;
IsFirstTry:= false;
end else begin
//Both failed!
break;
end;
end;
end;
end;
//Was it able to open any of them?
if Tipo = thcNone then begin
Tipo:= thcError;
raise Exception.Create('THojaCalc.create failed, may be no Office is installed?');
end;
//Add a blank document...
fVisible:= MakeVisible;
NewDoc;
end;
constructor THojaCalc.Create(Name: string; MakeVisible: boolean);
begin
Tipo:= thcNone;
//Store values...
FileName:= Name;
fVisible:= MakeVisible;
//Open program and document...
LoadProg;
LoadDoc;
end;
destructor THojaCalc.Destroy;
begin
CloseDoc;
CloseProg;
inherited;
end;
// *************************
// ** Loading the program **
// ** Excel or OpenOffice **
// *************************
procedure THojaCalc.LoadProg;
begin
if ProgLoaded then CloseProg;
if (UpperCase(ExtractFileExt(FileName))='.XLS') then begin
//Excel is the primary choice...
try
Programa:= CreateOleObject('Excel.Application');
except end;
if ProgLoaded then Tipo:= thcExcel;
end;
//Not lucky with Excel? Another filetype? Let's go with OpenOffice...
if Tipo = thcNone then begin
//Try with OpenOffice...
try
Programa:= CreateOleObject('com.sun.star.ServiceManager');
except end;
if ProgLoaded then Tipo:= thcOpenOffice;
end;
//Still no program loaded?
if not ProgLoaded then begin
Tipo:= thcError;
raise Exception.Create('THojaCalc.create failed, may be no Office is installed?');
end;
end;
procedure THojaCalc.CloseProg;
begin
if not Visible then CloseDoc;
if ProgLoaded then begin
try
if IsExcel then Programa.Quit;
//Next line made OO V2 not to work anymore as the next call to
//CreateOleObject('com.sun.star.ServiceManager') failed.
//if IsOpenOffice then Programa.Dispose;
Programa:= Unassigned;
finally end;
end;
Tipo:= thcNone;
end;
//Is there any prog loaded? Witch one?
function THojaCalc.GetProgLoaded: boolean;
begin
result:= not (VarIsEmpty(Programa) or VarIsNull(Programa));
end;
function THojaCalc.GetIsExcel: boolean;
begin
result:= (Tipo=thcExcel);
end;
function THojaCalc.GetIsOpenOffice: boolean;
begin
result:= (Tipo=thcOpenOffice);
end;
// ************************
// ** Loading a document **
// ************************
procedure THojaCalc.NewDoc;
var ooParams: variant;
begin
//Is the program running? (Excel or OpenOffice)
if not ProgLoaded then raise Exception.Create('No program loaded for the new document.');
//Is there a doc already loaded?
CloseDoc;
DeskTop:= Unassigned;
//OK, now try to create the doc...
if IsExcel then begin
Programa.WorkBooks.Add;
Programa.Visible:= Visible;
Document:= Programa.ActiveWorkBook;
ActiveSheet:= Document.ActiveSheet;
end;
if IsOpenOffice then begin
Desktop:= Programa.CreateInstance('com.sun.star.frame.Desktop');
//Optional parameters (visible)...
ooParams:= VarArrayCreate([0, 0], varVariant);
ooParams[0]:= ooCreateValue('Hidden', not Visible);
//Create the document...
Document:= Desktop.LoadComponentFromURL('private:factory/scalc', '_blank', 0, ooParams);
ActivateSheetByIndex(1);
end;
end;
procedure THojaCalc.LoadDoc;
var ooParams: variant;
begin
if FileName='' then exit;
//Is the program running? (Excel or OpenOffice)
if not ProgLoaded then LoadProg;
//Is there a doc already loaded?
CloseDoc;
DeskTop:= Unassigned;
//OK, now try to open the doc...
if IsExcel then begin
Programa.WorkBooks.Open(FileName,3);
Programa.Visible:= Visible;
Document:= Programa.ActiveWorkBook;
ActiveSheet:= Document.ActiveSheet;
end;
if IsOpenOffice then begin
Desktop:= Programa.CreateInstance('com.sun.star.frame.Desktop');
//Optional parameters (visible)...
ooParams:= VarArrayCreate([0, 0], varVariant);
//Next line stop working OK on OOo V2: Created blind, always blind!
//so now it is create as visible, then set to non visible if requested
//ooParams[0]:= ooCreateValue('Hidden', not Visible);
ooParams[0]:= ooCreateValue('Hidden', false); //Create as visible, then make it not visible if necesary
//Open the document...
Document:= Desktop.LoadComponentFromURL(FileName2URL(FileName), '_blank', 0, ooParams);
ActiveSheet:= ActivateSheetByIndex(1);
//If has to be non visible, set it now...
if not visible then
Document.getCurrentController.getFrame.getContainerWindow.setVisible(false);
end;
if Tipo=thcNone then
raise Exception.Create('No puedo leer el fichero "'+FileName+'" al no estar presente el programa necesario.');
end;
function THojaCalc.SaveDoc: boolean;
begin
result:= false;
if DocLoaded then begin
if IsExcel then begin
Document.Save;
result:= true;
end;
if IsOpenOffice then begin
Document.Store;
result:= true;
end;
end;
end;
//Added by Massimiliano Gozzi V0.92
//AsEXcel97 taken form V0.93 by Rômulo Silva Ramos
function THojaCalc.SaveDocAs(Name: string; AsExcel97: boolean = false): boolean;
var ooParams: variant;
begin
result:= false;
if DocLoaded then begin
if IsExcel then begin
Document.Saveas(Name);
FileName:= Name;
result:= true;
end;
if IsOpenOffice then begin
//I may need 1 or 2 params...
if AsExcel97 then
ooParams:= VarArrayCreate([0, 1], varVariant)
else
ooParams:= VarArrayCreate([0, 0], varVariant);
//First one for prompting on overwrite (good idea!)
ooParams[0]:= ooCreateValue('Overwrite', false);
//Optionally tell OpenOffiec to use Excel97 .xls format
if AsExcel97 then
ooParams[1]:= ooCreateValue('FilterName', 'MS Excel 97');
//Do the save!
Document.StoreAsUrl(FileName2URL(Name), ooParams);
FileName:= Name;
result:= true;
end;
end;
end;
//Print the Doc...
function THojaCalc.PrintDoc: boolean;
var ooParams: variant;
begin
result:= false;
if DocLoaded then begin
if IsExcel then begin
Document.PrintOut;
result:= true;
end;
if IsOpenOffice then begin
//NOTE: OpenOffice will print all sheets with Printable areas, but if no
//printable areas are defined in the doc, it will print all entire sheets.
//Optional parameters (wait until fully sent to printer)...
ooParams:= VarArrayCreate([0, 0], varVariant);
ooParams[0]:= ooCreateValue('Wait', true);
Document.Print(ooParams);
result:= true;
end;
end;
end;
procedure THojaCalc.ShowPrintPreview;
begin
if DocLoaded then begin
//Force visibility of the doc...
Visible:= true;
if IsExcel then
Document.PrintOut(,,,true);
if IsOpenOffice then
ooDispatch('.uno:PrintPreview', Unassigned);
end;
end;
procedure THojaCalc.SetVisible(v: boolean);
begin
if DocLoaded and (v<>fVisible) then begin
if IsExcel then
Programa.Visible:= v;
if IsOpenOffice then
Document.getCurrentController.getFrame.getContainerWindow.setVisible(v);
fVisible:= v;
end;
end;
procedure THojaCalc.CloseDoc;
begin
if DocLoaded then begin
//Close it...
try
if IsOpenOffice then Document.Dispose;
if IsExcel then Document.close;
finally end;
//Clean up both "pointer"...
Document:= Null;
ActiveSheet:= Null;
end;
end;
function THojaCalc.GetDocLoaded: boolean;
begin
result:= not (VarIsEmpty(Document) or VarIsNull(Document));
end;
// *********************
// ** Managing sheets **
// *********************
function THojaCalc.GetCountSheets: integer;
begin
result:= 0;
if DocLoaded then begin
if IsExcel then result:= Document.Sheets.count;
if IsOpenOffice then result:= Document.getSheets.GetCount;
end;
end;
//Index is 1 based in Excel, but OpenOffice uses it 0-based
//Here we asume 1-based so OO needs to activate (nIndex-1)
function THojaCalc.ActivateSheetByIndex(nIndex: integer): boolean;
begin
result:= false;
if DocLoaded then begin
//Exists this sheet number?
if (nIndex<1) then
raise Exception.Create('Can not activate sheet #'+IntToStr(nIndex));
while (nIndex>CountSheets) do begin
ActivateSheetByIndex(CountSheets);
AddNewSheet('Nueva hoja '+IntToStr(CountSheets+1));
sleep(100); //Needs time to do it!
end;
//Activate it now...
if IsExcel then begin
Document.Sheets[nIndex].activate;
ActiveSheet:= Document.ActiveSheet;
result:= true;
end;
if IsOpenOffice then begin
ActiveSheet:= Document.getSheets.getByIndex(nIndex-1);
result:= true;
end;
sleep(100); //Asyncronus, so better give it time to make the change
end;
end;
//Find a sheet by its name...
function THojaCalc.ActivateSheetByName(SheetName: string; CaseSensitive: boolean): boolean;
var
OldActiveSheet: variant;
i: integer;
begin
result:= false;
if DocLoaded then begin
if CaseSensitive then begin
//Find the EXACT name...
if IsExcel then begin
Document.Sheets[SheetName].Select;
ActiveSheet:= Document.ActiveSheet;
result:= true;
end;
if IsOpenOffice then begin
ActiveSheet:= Document.getSheets.getByName(SheetName);
result:= true;
end;
end else begin
//Find the Sheet regardless of the case...
OldActiveSheet:= ActiveSheet;
for i:= 1 to GetCountSheets do begin
ActivateSheetByIndex(i);
if UpperCase(ActiveSheetName)=UpperCase(SheetName) then begin
result:= true;
Exit;
end;
end;
//If not found, let the old active sheet active...
ActiveSheet:= OldActiveSheet;
end;
end;
end;
//Name of the active sheet?
function THojaCalc.GetActiveSheetName: string;
begin
if DocLoaded then begin
if IsExcel then
result:= ActiveSheet.Name;
if IsOpenOffice then
result:= ActiveSheet.GetName;
end;
end;
procedure THojaCalc.SetActiveSheetName(NewName: string);
begin
if DocLoaded then begin
//Clean name first...
NewName := ValidateSheetName(NewName);
if IsExcel then
Programa.ActiveSheet.Name:= NewName;
if IsOpenOffice then begin
ActiveSheet.setName(NewName);
//This code always changes the name of "visible" sheet, not active one!
//ooParams:= VarArrayCreate([0, 0], varVariant);
//ooParams[0]:= ooCreateValue('Name', NewName);
//ooDispatch('.uno:RenameTable', ooParams);
end;
end;
end;
//Check for sheet protection (password)...
function THojaCalc.IsActiveSheetProtected: boolean;
begin
result:= false;
if DocLoaded then begin
if IsExcel then
result:= ActiveSheet.ProtectContents;
if IsOpenOffice then
result:= ActiveSheet.IsProtected;
end;
end;
//WARNING: This function is NOT dual, only works for Excel docs!
//Send active sheet to default printer (as seen in preview window)...
function THojaCalc.PrintActiveSheet: boolean;
begin
result:= false;
if DocLoaded then begin
if IsExcel then begin
ActiveSheet.PrintOut;
result:= true;
end;
if IsOpenOffice then begin
raise Exception.Create('Function "PrintActiveSheet" still not working in OpenOffice!');
//ActiveSheet.Print;
result:= false;
end;
end;
end;
//WARNING: This function is NOT dual, only works for Excel docs!
//Select and print sheets from 1 upto -excluded- the one with that name.
//It is interesting for understanding how to pass an array of objects to excel.
function THojaCalc.PrintSheetsUntil(LastSheetName: string): boolean;
var
i, last: integer;
Hojas: variant;
begin
result:= false;
if DocLoaded then begin
if IsExcel then begin
//Macro from Excel:
// Sheets(Array("Hoja1", "Hoja2")).Select
// ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True
//
//Witch sheet number correspond to the one previous to "LastSheetName"?
Last:= 0;
for i:= 2 to CountSheets do begin
ActivateSheetByIndex(i);
if UpperCase(ActiveSheetName)=UpperCase(LastSheetName) then begin
Last:= i-1;
break;
end;
end;
//Not found?
if Last=0 then exit;
//Create an array of variants -windows standard type- this big...
Hojas:= VarArrayCreate([1, Last], varVariant);
//Fill it with the Sheet names...
for i:= 1 to Last do begin
ActivateSheetByIndex(i);
Hojas[i]:= ActiveSheetName;
end;
//Print all this array of sheets...
Programa.Sheets[Hojas].Select;
Programa.ActiveWindow.SelectedSheets.PrintOut;
//Done!
result:= true;
end;
if IsOpenOffice then begin
raise Exception.Create('Function "PrintSheetsUntil" not working in OpenOffice!');
result:= false;
end;
end;
end;
//Add a new sheet, name it, and make it the active sheet...
procedure THojaCalc.AddNewSheet(NewName: string);
var
ooSheets: variant;
begin
NewName := ValidateSheetName(NewName);
if DocLoaded then begin
if IsExcel then begin
Document.WorkSheets.Add(null, Document.ActiveSheet, 1);
Document.ActiveSheet.Name:= NewName;
//Active sheet has move to this new one, so I need to update the var
ActiveSheet:= Document.ActiveSheet;
end;
if IsOpenOffice then begin
ooSheets:= Document.getSheets;
ooSheets.insertNewByName(NewName, 1);
//Redefine active sheet to this new one
ActiveSheet:= ooSheets.getByName(NewName);
end;
end;
end;
//Clean a Sheet name so it will not cause problems
function THojaCalc.ValidateSheetName(Name: string): string;
begin
result := StringReplace(name, ':', '_',[rfReplaceAll]);
result := StringReplace(result, '/', '_',[rfReplaceAll]);
result := StringReplace(result, '\', '_',[rfReplaceAll]);
result := StringReplace(result, '?', '_',[rfReplaceAll]);
result := StringReplace(result, '*', '_',[rfReplaceAll]);
result := StringReplace(result, '[', '_',[rfReplaceAll]);
result := StringReplace(result, ']', '_',[rfReplaceAll]);
result := StringReplace(result, '"', '_',[rfReplaceAll]);
if (Trim(result)='') then
result:= 'Plan' + IntToStr(CountSheets);
result:= Copy(result, 1, 31);
end;
// ************************
// ** Manage the cells **
// ** in the ActiveSheet **
// ************************
//Read/Write cell text (formula en Excel) by index
//OpenOffice start at cell (0,0) while Excel at (1,1)
//Also, Excel uses (row, col) and OpenOffice uses (col, row)
function THojaCalc.GetCellText(row, col: integer): string;
begin
if DocLoaded then begin
if IsExcel then result:= ActiveSheet.Cells[row, col].Text;
if IsOpenOffice then result:= ActiveSheet.getCellByPosition(col-1, row-1).getFormula;
end;
end;
procedure THojaCalc.SetCellText(row, col: integer; Txt: string);
begin
if DocLoaded then begin
if IsExcel then begin
ActiveSheet.Cells[row, col].Select;
Programa.ActiveCell.Value:= Txt;
end;
if IsOpenOffice then
ActiveSheet.getCellByPosition(col-1, row-1).setFormula(Txt);
end;
end;
//Read/Write cell text (formula in excel) by name instead of position
//For instance, you can set the value for cell 'NewSheet!A12' or similar
//NOTE: If range contains several cells, first one will be used.
function THojaCalc.GetCellTextByName(Range: string): string;
var OldActiveSheet: variant;
begin
if DocLoaded then begin
if IsExcel then begin
result:= Programa.Range[Range].Text; //Set 'Formula' but Get 'Text';
end;
if IsOpenOffice then begin
OldActiveSheet:= ActiveSheet;
//If range is in the form 'NewSheet!A1' then first change sheet to 'NewSheet'
if pos('!', Range) > 0 then begin
//Activate the proper sheet...
if not ActivateSheetByName(Copy(Range, 1, pos('!', Range)-1), false) then
raise Exception.Create('Sheet "'+Copy(Range, 1, pos('!', Range)-1)+'" not present in the document.');
Range:= Copy(Range, pos('!', Range)+1, 999);
end;
result:= ActiveSheet.getCellRangeByName(Range).getCellByPosition(0,0).getFormula;
ActiveSheet:= OldActiveSheet;
end;
end;
end;
procedure THojaCalc.SetCellTextByName(Range: string; Txt: string);
var OldActiveSheet: variant;
begin
if DocLoaded then begin
if IsExcel then begin
Programa.Range[Range].formula:= Txt;
end;
if IsOpenOffice then begin
OldActiveSheet:= ActiveSheet;
//If range is in the form 'NewSheet!A1' then first change sheet to 'NewSheet'
if pos('!', Range) > 0 then begin
//Activate the proper sheet...
if not ActivateSheetByName(Copy(Range, 1, pos('!', Range)-1), false) then
raise Exception.Create('Sheet "'+Copy(Range, 1, pos('!', Range)-1)+'" not present in the document.');
Range:= Copy(Range, pos('!', Range)+1, 999);
end;
ActiveSheet.getCellRangeByName(Range).getCellByPosition(0,0).SetFormula(Txt);
ActiveSheet:= OldActiveSheet;
end;
end;
end;
procedure THojaCalc.BackgroundColor(row,col: integer; color: TColor);
begin
if DocLoaded then begin
if IsExcel then begin
Programa.ActiveSheet.Cells[row,col].Interior.Color := color;
end;
if IsOpenOffice then begin
ActiveSheet.getCellByPosition(col-1, row-1).CellBackColor := color;
end;
end;
end;
procedure THojaCalc.FontSize(row, col, size: integer);
begin
if DocLoaded then begin
if IsExcel then begin
Programa.ActiveSheet.Cells[row,col].Font.Size := size;
end;
if IsOpenOffice then begin
ActiveSheet.getCellByPosition(col-1, row-1).getText.createTextCursor.CharHeight:= size;
end;
end;
end;
procedure THojaCalc.Bold(row,col: integer);
const ooBold: integer = 150; //150 = com.sun.star.awt.FontWeight.BOLD
begin
if DocLoaded then begin
if IsExcel then begin
Programa.ActiveSheet.Cells[row,col].Font.Bold:= true;
end;
if IsOpenOffice then begin
ActiveSheet.getCellByPosition(col-1, row-1).getText.createTextCursor.CharWeight:= ooBold;
end;
end;
end;
procedure THojaCalc.ColumnWidth(col, width: integer); //Width in 1/100 of mm.
begin
if DocLoaded then begin
if IsExcel then begin
//Excel use the width of '0' as the unit, we do an aproximation: Width '0' = 2 mm.
Programa.ActiveSheet.Cells[1, col].ColumnWidth:= width/100/3;
end;
if IsOpenOffice then begin
ActiveSheet.getCellByPosition(col-1, 0).getColumns.getByIndex(0).Width:= width;
end;
end;
end;
// ***************************
// ** OpenOffice only stuff **
// ***************************
//Change 'C:\File.txt' into 'file:///c:/File.txt' (for OpenOffice OpenURL)
function THojaCalc.FileName2URL(FileName: string): string;
begin
result:= '';
if LowerCase(copy(FileName,1,8))<>'file:///' then
result:= 'file:///';
result:= result + StringReplace(FileName, '\', '/', [rfReplaceAll, rfIgnoreCase]);
end;
function THojaCalc.ooCreateValue(ooName: string; ooData: variant): variant;
var
ooReflection: variant;
begin
if IsOpenOffice then begin
ooReflection:= Programa.createInstance('com.sun.star.reflection.CoreReflection');
ooReflection.forName('com.sun.star.beans.PropertyValue').createObject(result);
result.Name := ooName;
result.Value:= ooData;
end else begin
raise Exception.Create('ooValue imposible to create, load OpenOffice first!');
end;
end;
procedure THojaCalc.ooDispatch(ooCommand: string; ooParams: variant);
var
ooDispatcher, ooFrame: variant;
begin
if DocLoaded and IsOpenOffice then begin
if (VarIsEmpty(ooParams) or VarIsNull(ooParams)) then
ooParams:= VarArrayCreate([0, -1], varVariant);
ooFrame:= Document.getCurrentController.getFrame;
ooDispatcher:= Programa.createInstance('com.sun.star.frame.DispatchHelper');
ooDispatcher.executeDispatch(ooFrame, ooCommand, '', 0, ooParams);
end else begin
raise Exception.Create('Dispatch imposible, load a OpenOffice doc first!');
end;
end;
end.
|
Last edited by bitfarmer on Wed Jan 20, 2010 2:56 am; edited 3 times in total |
|
| Back to top |
|
 |
Petr Newbie

Joined: 03 May 2006 Posts: 2
|
Posted: Wed May 03, 2006 3:36 am Post subject: OpenOffice |
|
|
Hi,
the code is Ok. I have only problems by using function SaveDoc. Using this function causes : com.sun..star.ErrorIOException, what is the problem ? Can you please send any advise ?
Thank you
Petr |
|
| Back to top |
|
 |
nisbus Newbie

Joined: 01 Jun 2006 Posts: 1
|
Posted: Thu Jun 01, 2006 11:56 am Post subject: CellCount |
|
|
Hi,
Thanks alot for cracking this.
I'm using this to export StringGrids from Delphi to OpenOffice and Excel.
I would like to be able to read OpenOffice Calc and Excel documents into a StringGrid as well but I don't know how to count the rows and columns within the open document.
Thank again,
nisbus |
|
| Back to top |
|
 |
Petr Newbie

Joined: 03 May 2006 Posts: 2
|
Posted: Thu Jun 01, 2006 10:16 pm Post subject: |
|
|
Hi
my opinien is, that the only possible way is to open the document as non visible then count the rows and columns and then the document close. If you know any other better solution, I am interested in it too.
Thank
Petr |
|
| Back to top |
|
 |
ChrBlack General User

Joined: 01 Jun 2006 Posts: 7 Location: Hungary
|
Posted: Tue Jun 06, 2006 10:47 pm Post subject: OOo2.0.2 |
|
|
Hi!
This code works with OpenOffice 2.x? I have some problems with OO functions/procedures in the code above, while Excel code works fine. For examlpe ActiveSheetByName, ActiveSheetByIndex, OpenDoc,SaveDoc. May something changed in OO 2.x, while the code works with OO 1.x ?
Cheers:
ChrBlack |
|
| Back to top |
|
 |
RomuloRamos Newbie

Joined: 02 Oct 2009 Posts: 1
|
Posted: Fri Oct 02, 2009 9:28 am Post subject: |
|
|
I made some modification on the code, this is my way to thanks the original code:
| Code: |
// ********************************************
// ** Object for dual SpreadSheet managing **
// ** using Excel or OpenOffice automaticaly **
// ** By: Sergio Hernandez **
// ** oficina(at)hcsoft.net, CopyLeft 2004 **
// ** Version 0.92 18-05-2004 (DDMMYYYY) **
// ** Use it freely, change it, etc. **
// ********************************************
// ********************************************
// ** Modify By: Rômulo Silva Ramos **
// ** Version 0.93 01-10-2009 (DDMMYYYY) **
// ********************************************
{EXAMPLE OF USE
//Create object: We have two flavours:
//(A) from an existing file...
HCalc:= TSheetCalc.create(OpenDialog.FileName, false);
//(B) from a blank document...
HCalc:= TSheetCalc.create(thcOpenOffice); //OpenOffice doc if possible, please
HCalc.FileName:= 'C:\MyNewDoc'; //Needs a file name before you SaveDoc!
//--end of creation.
HCalc.ActivateSheetByIndex(2); //Activate second sheet
if HCalc.IsActiveSheetProtected then
ShowMessage('2nd sheet of name "'+HCalc.ActiveSheetName+'" IS protected');
//Change a cell value (well, change formula, not the double float value)
if HCalc.CellText[i,2] = '' then HCalc.CellText[i,2] := 'Hello world!';
HCalc.AddNewSheet('New Sheet');
HCalc.PrintDoc;
HCalc.SaveDoc;
HCalc.Free;
Other exemple:
var
Plan : TSheetCalc;
begin
Plan := TSheetCalc.Create(thcExcel,false);
Plan.FileName := arquivo;
Plan.ActivateSheetByIndex(1);
Plan.CellText[1,1] := 'Abstraction complete';
Plan.SaveDoc;
Plan.Visible := True;
begin
}
{TODO LIST:
-PrintActiveSheet is not working for OpenOffice (is it even possible?)
-A way to write a date in a cell changing also the format (Excel is herratic in that)
}
{CHANGE LOG:
V0.93:
-FontSize(Row, Col, Size): change font size in that cell.
-Change AddNewSheet to add a new sheet in end at sheet list
-Add ValidateSheetName to validate sheet names when adding or renaming a sheet
-Change in SaveDoc to use SaveAs/StoreAsUrl
-Change name 'Hoja' para 'Sheet'
-Change name 'Programa' para 'SheetSoftware'
-Change exception.create messages:
'No puedo leer el fichero "'+FileName+'" al no estar presente el programa necesario.'
to
'Not able to read the file "'+FileName+'". Probably not exist a software installed to open it.'
-Add other exemple of utilization
V0.92:
-SetActiveSheetName didn't change the name to the right sheet on OpenOffice.
-PrintPreview: New procedure to show up the print preview window.
-Bold(Row, Col): Make bold the text in that cell.
-ColumnWidth(col, width): To change a column width.
V0.91:
-NewDoc: New procedure for creating a blank doc (used in create)
-Create from empty doc adds a blank document and take visibility as parameter.
-New functions ooCreateValue and ooDispatch to clean up the code.
-ActiveSheetName: Now is a read-write property, not a read-only function.
-Visible: Now is a read-write property instead of a create param only.
V0.9:
-Create from empty doc now tries both programs (if OO fails try to use Excel).
-CellTextByName: Didn't work on Excel docs.
}
unit uSCPPlanilhaEletronica;
interface
uses Variants, SysUtils, ComObj,Graphics;
//thcError: Tried to open but both failes
//thcNone: Haven't tried still to open any
type TTipoSheetCalc = (thcError, thcNone, thcExcel, thcOpenOffice);
type TSheetCalc = class(TObject)
private
fVisible: boolean;
//Program loaded stuff...
procedure LoadProg;
procedure CloseProg;
function GetProgLoaded: boolean;
procedure NewDoc;
procedure LoadDoc;
procedure CloseDoc;
function GetDocLoaded: boolean;
function GetIsExcel: boolean;
function GetIsOpenOffice: boolean;
procedure SetVisible(v: boolean);
//Sheets stuff..
function GetCountSheets: integer;
function GetActiveSheetName: string;
procedure SetActiveSheetName(NewName: string);
//Cells stuff...
function GetCellText(row,col: integer): string;
procedure SetCellText(row,col: integer; Txt: string);
function GetCellTextByName(Range: string): string;
procedure SetCellTextByName(Range: string; Txt: string);
//OpenOffice only stuff...
function FileName2URL(FileName: string): string;
procedure ooDispatch(ooCommand: string; ooParams: variant);
function ooCreateValue(ooName: string; ooData: variant): variant;
//aux functions
function ValidateSheetName(Name:string): string;
public
Tipo: TTipoSheetCalc; //Witch program was used to manage the doc?
FileName: string; //In windows FileName format C:\MyDoc.XXX
SheetSoftware: variant; //Excel or OpenOfice instance created.
DeskTop: variant; //OpenOffice desktop reference (not used now).
Document: variant; //Document opened.
ActiveSheet: variant; //Active sheet.
//Object internals...
constructor Create(Name: string; MakeVisible: boolean); overload;
constructor Create(MyTipo: TTipoSheetCalc; MakeVisible: boolean); overload;
destructor Destroy; override;
//Program loaded stuff...
function SaveDoc: boolean;
function PrintDoc: boolean;
procedure ShowPrintPreview;
property ProgLoaded: boolean read GetProgLoaded;
property DocLoaded: boolean read GetDocLoaded;
property IsExcel: boolean read GetIsExcel;
property IsOpenOffice: boolean read GetIsOpenOffice;
property Visible: boolean read fVisible write SetVisible;
//Sheets stuff...
function ActivateSheetByIndex(nIndex: integer): boolean;
function ActivateSheetByName(SheetName: string; CaseSensitive: boolean): boolean;
function IsActiveSheetProtected: boolean;
function PrintActiveSheet: boolean;
procedure AddNewSheet(NewName: string);
property CountSheets: integer read GetCountSheets;
property ActiveSheetName: string read GetActiveSheetName write SetActiveSheetName;
//Cells stuff...
procedure BackgroundColor(row,col: integer; color:TColor);
procedure FontSize(row,col,size: integer);
procedure Bold(row,col: integer);
procedure ColumnWidth(col, width: integer); //Width in 1/100 of mm.
property CellText[f,c: integer]: string read GetCellText write SetCellText;
property CellTextByName[Range: string]: string read GetCellTextByName write SetCellTextByName;
end;
implementation
// ************************
// ** Create and destroy **
// ************************
//Create with an empty doc of requested type (use thcExcel or thcOpenOffice)
//Remember to define FileName before calling to SaveDoc
constructor TSheetCalc.Create(MyTipo: TTipoSheetCalc; MakeVisible: boolean);
var
i: integer;
IsFirstTry: boolean;
begin
//Close all opened things first...
if DocLoaded then CloseDoc;
if ProgLoaded then CloseProg;
//I will try to open twice, so if Excel fails, OpenOffice is used instead
IsFirstTry:= true;
for i:= 1 to 2 do begin
//Try to open OpenOffice...
if (MyTipo = thcOpenOffice) or (MyTipo = thcNone)then begin
SheetSoftware:= CreateOleObject('com.sun.star.ServiceManager');
if ProgLoaded then begin
Tipo:= thcOpenOffice;
break;
end else begin
if IsFirstTry then begin
//Try Excel as my second choice
MyTipo:= thcExcel;
IsFirstTry:= false;
end else begin
//Both failed!
break;
end;
end;
end;
//Try to open Excel...
if (MyTipo = thcExcel) or (MyTipo = thcNone) then begin
SheetSoftware:= CreateOleObject('Excel.Application');
if ProgLoaded then begin
Tipo:= thcExcel;
break;
end else begin
if IsFirstTry then begin
//Try OpenOffice as my second choice
MyTipo:= thcOpenOffice;
IsFirstTry:= false;
end else begin
//Both failed!
break;
end;
end;
end;
end;
//Was it able to open any of them?
if Tipo = thcNone then begin
Tipo:= thcError;
raise exception.create('TSheetCalc.create failed, may be no Office is installed?');
end;
//Add a blank document...
fVisible:= MakeVisible;
NewDoc;
end;
constructor TSheetCalc.Create(Name: string; MakeVisible: boolean);
begin
//Store values...
FileName:= Name;
fVisible:= MakeVisible;
//Open program and document...
LoadProg;
LoadDoc;
end;
destructor TSheetCalc.Destroy;
begin
CloseDoc;
CloseProg;
inherited;
end;
// *************************
// ** Loading the program **
// ** Excel or OpenOffice **
// *************************
procedure TSheetCalc.LoadProg;
begin
if ProgLoaded then CloseProg;
if (UpperCase(ExtractFileExt(FileName))='.XLS') then begin
//Excel is the primary choice...
SheetSoftware:= CreateOleObject('Excel.Application');
if ProgLoaded then Tipo:= thcExcel;
end;
//Not lucky with Excel? Another filetype? Let's go with OpenOffice...
if Tipo = thcNone then begin
//Try with OpenOffice...
SheetSoftware:= CreateOleObject('com.sun.star.ServiceManager');
if ProgLoaded then Tipo:= thcOpenOffice;
end;
//Still no program loaded?
if not ProgLoaded then begin
Tipo:= thcError;
raise Exception.create('TSheetCalc.create failed, may be no Office is installed?');
end;
end;
procedure TSheetCalc.CloseProg;
begin
if DocLoaded then CloseDoc;
if ProgLoaded then begin
try
if IsExcel then SheetSoftware.Quit;
SheetSoftware:= Unassigned;
finally end;
end;
Tipo:= thcNone;
end;
//Is there any prog loaded? Witch one?
function TSheetCalc.GetProgLoaded: boolean;
begin
result:= not (VarIsEmpty(SheetSoftware) or VarIsNull(SheetSoftware));
end;
function TSheetCalc.GetIsExcel: boolean;
begin
result:= (Tipo=thcExcel);
end;
function TSheetCalc.GetIsOpenOffice: boolean;
begin
result:= (Tipo=thcOpenOffice);
end;
// ************************
// ** Loading a document **
// ************************
procedure TSheetCalc.NewDoc;
var ooParams: variant;
begin
//Is the program running? (Excel or OpenOffice)
if not ProgLoaded then raise exception.create('No program loaded for the new document.');
//Is there a doc already loaded?
if DocLoaded then CloseDoc;
DeskTop:= Unassigned;
//OK, now try to create the doc...
if IsExcel then begin
SheetSoftware.WorkBooks.Add;
SheetSoftware.Visible:= Visible;
Document:= SheetSoftware.ActiveWorkBook;
ActiveSheet:= Document.ActiveSheet;
end;
if IsOpenOffice then begin
Desktop:= SheetSoftware.CreateInstance('com.sun.star.frame.Desktop');
//Optional parameters (visible)...
ooParams:= VarArrayCreate([0, 0], varVariant);
ooParams[0]:= ooCreateValue('Hidden', not Visible);
//Create the document...
Document:= Desktop.LoadComponentFromURL('private:factory/scalc', '_blank', 0, ooParams);
ActivateSheetByIndex(1);
end;
end;
procedure TSheetCalc.LoadDoc;
var ooParams: variant;
begin
if FileName='' then exit;
//Is the program running? (Excel or OpenOffice)
if not ProgLoaded then LoadProg;
//Is there a doc already loaded?
if DocLoaded then CloseDoc;
DeskTop:= Unassigned;
//OK, now try to open the doc...
if IsExcel then begin
SheetSoftware.WorkBooks.Open(FileName,3);
SheetSoftware.Visible:= Visible;
Document:= SheetSoftware.ActiveWorkBook;
ActiveSheet:= Document.ActiveSheet;
end;
if IsOpenOffice then begin
Desktop:= SheetSoftware.CreateInstance('com.sun.star.frame.Desktop');
//Optional parameters (visible)...
ooParams:= VarArrayCreate([0, 0], varVariant);
ooParams[0]:= ooCreateValue('Hidden', not Visible);
//Open the document...
Document:= Desktop.LoadComponentFromURL(FileName2URL(FileName), '_blank', 0, ooParams);
ActiveSheet:= ActivateSheetByIndex(1);
end;
if Tipo=thcNone then
raise exception.create('Not able to read the file "'+FileName+'". Probably not exist a software installed to open it.');
end;
function TSheetCalc.SaveDoc: boolean;
var ooParams: variant;
begin
result:= false;
if DocLoaded then begin
if IsExcel then begin
Document.SaveAs(FileName);
result:= true;
end;
if IsOpenOffice then begin
ooParams:= VarArrayCreate([0, 0], varVariant);
ooParams[0]:= ooCreateValue('FilterName', 'MS Excel 97');
Document.StoreAsUrl('file:///'+StringReplace(FileName,'\','/',[rfReplaceAll]),ooParams);
result:= true;
end;
end;
end;
//Print the Doc...
function TSheetCalc.PrintDoc: boolean;
var ooParams: variant;
begin
result:= false;
if DocLoaded then begin
if IsExcel then begin
Document.PrintOut;
result:= true;
end;
if IsOpenOffice then begin
//NOTE: OpenOffice will print all sheets with Printable areas, but if no
//printable areas are defined in the doc, it will print all entire sheets.
//Optional parameters (wait until fully sent to printer)...
ooParams:= VarArrayCreate([0, 0], varVariant);
ooParams[0]:= ooCreateValue('Wait', true);
Document.Print(ooParams);
result:= true;
end;
end;
end;
procedure TSheetCalc.ShowPrintPreview;
begin
if DocLoaded then begin
//Force visibility of the doc...
Visible:= true;
if IsExcel then
Document.PrintOut(,,,true);
if IsOpenOffice then
ooDispatch('.uno:PrintPreview', Unassigned);
end;
end;
procedure TSheetCalc.SetVisible(v: boolean);
begin
if DocLoaded and (v<>fVisible) then begin
if IsExcel then
SheetSoftware.Visible:= v;
if IsOpenOffice then
Document.getCurrentController.getFrame.getContainerWindow.setVisible(v);
fVisible:= v;
end;
end;
procedure TSheetCalc.CloseDoc;
begin
if DocLoaded then begin
//Close it...
try
if IsOpenOffice then Document.Dispose;
if IsExcel then Document.close;
finally end;
//Clean up both "pointer"...
Document:= Null;
ActiveSheet:= Null;
end;
end;
function TSheetCalc.GetDocLoaded: boolean;
begin
result:= not (VarIsEmpty(Document) or VarIsNull(Document));
end;
// *********************
// ** Managing sheets **
// *********************
function TSheetCalc.GetCountSheets: integer;
begin
result:= 0;
if DocLoaded then begin
if IsExcel then result:= Document.Sheets.count;
if IsOpenOffice then result:= Document.getSheets.GetCount;
end;
end;
//Index is 1 based in Excel, but OpenOffice uses it 0-based
//Here we asume 1-based so OO needs to activate (nIndex-1)
function TSheetCalc.ActivateSheetByIndex(nIndex: integer): boolean;
begin
result:= false;
if DocLoaded then begin
if IsExcel then begin
Document.Sheets[nIndex].activate;
ActiveSheet:= Document.ActiveSheet;
result:= true;
end;
if IsOpenOffice then begin
ActiveSheet:= Document.getSheets.getByIndex(nIndex-1);
result:= true;
end;
sleep(100); //Asyncronus, so better give it time to make the change
end;
end;
//Find a sheet by its name...
function TSheetCalc.ActivateSheetByName(SheetName: string; CaseSensitive: boolean): boolean;
var
OldActiveSheet: variant;
i: integer;
begin
result:= false;
if DocLoaded then begin
if CaseSensitive then begin
//Find the EXACT name...
if IsExcel then begin
Document.Sheets[SheetName].Select;
ActiveSheet:= Document.ActiveSheet;
result:= true;
end;
if IsOpenOffice then begin
ActiveSheet:= Document.getSheets.getByName(SheetName);
result:= true;
end;
end else begin
//Find the Sheet regardless of the case...
OldActiveSheet:= ActiveSheet;
for i:= 1 to GetCountSheets do begin
ActivateSheetByIndex(i);
if UpperCase(ActiveSheetName)=UpperCase(SheetName) then begin
result:= true;
Exit;
end;
end;
//If not found, let the old active sheet active...
ActiveSheet:= OldActiveSheet;
end;
end;
end;
//Name of the active sheet?
function TSheetCalc.GetActiveSheetName: string;
begin
if DocLoaded then begin
if IsExcel then
result:= ActiveSheet.Name;
if IsOpenOffice then
result:= ActiveSheet.GetName;
end;
end;
procedure TSheetCalc.SetActiveSheetName(NewName: string);
begin
NewName := ValidateSheetName(NewName);
if DocLoaded then begin
if IsExcel then
SheetSoftware.ActiveSheet.Name:= NewName;
if IsOpenOffice then begin
ActiveSheet.setName(NewName);
//This code always changes the name of "visible" sheet, not active one!
//ooParams:= VarArrayCreate([0, 0], varVariant);
//ooParams[0]:= ooCreateValue('Name', NewName);
//ooDispatch('.uno:RenameTable', ooParams);
end;
end;
end;
//Check for sheet protection (password)...
function TSheetCalc.IsActiveSheetProtected: boolean;
begin
result:= false;
if DocLoaded then begin
if IsExcel then
result:= ActiveSheet.ProtectContents;
if IsOpenOffice then
result:= ActiveSheet.IsProtected;
end;
end;
//WARNING: This function is NOT dual, only works for Excel docs!
//Send active sheet to default printer (as seen in preview window)...
function TSheetCalc.PrintActiveSheet: boolean;
begin
result:= false;
if DocLoaded then begin
if IsExcel then begin
ActiveSheet.PrintOut;
result:= true;
end;
if IsOpenOffice then begin
raise exception.create('Function "PrintActiveSheet" still not working in OpenOffice!');
//ActiveSheet.Print;
result:= false;
end;
end;
end;
//Add a new sheet, name it, and make it the active sheet...
procedure TSheetCalc.AddNewSheet(NewName: string);
var
ooSheets: variant;
begin
NewName := ValidateSheetName(NewName);
if DocLoaded then begin
if IsExcel then begin
Document.WorkSheets.Add;
Document.ActiveSheet.Move(After:=Document.Sheets[CountSheets]);
Document.ActiveSheet.Name:= NewName;
//Active sheet has move to this new one, so I need to update the var
ActiveSheet:= Document.ActiveSheet;
end;
if IsOpenOffice then begin
ooSheets:= Document.getSheets;
ooSheets.insertNewByName(NewName, CountSheets);
//Redefine active sheet to this new one
ActiveSheet:= ooSheets.getByName(NewName);
end;
end;
end;
// ************************
// ** Manage the cells **
// ** in the ActiveSheet **
// ************************
//Read/Write cell text (formula en Excel) by index
//OpenOffice start at cell (0,0) while Excel at (1,1)
//Also, Excel uses (row, col) and OpenOffice uses (col, row)
function TSheetCalc.GetCellText(row, col: integer): string;
begin
if DocLoaded then begin
if IsExcel then result:= ActiveSheet.Cells[row, col].Formula; //.Text;
if IsOpenOffice then result:= ActiveSheet.getCellByPosition(col-1, row-1).getFormula;
end;
end;
procedure TSheetCalc.SetCellText(row, col: integer; Txt: string);
begin
if DocLoaded then begin
if IsExcel then ActiveSheet.Cells[row, col].Formula:= Txt;
if IsOpenOffice then ActiveSheet.getCellByPosition(col-1, row-1).setFormula(Txt);
end;
end;
//Read/Write cell text (formula in excel) by name instead of position
//For instance, you can set the value for cell 'NewSheet!A12' or similar
//NOTE: If range contains several cells, first one will be used.
function TSheetCalc.GetCellTextByName(Range: string): string;
var OldActiveSheet: variant;
begin
if DocLoaded then begin
if IsExcel then begin
result:= SheetSoftware.Range[Range].Text; //Set 'Formula' but Get 'Text';
end;
if IsOpenOffice then begin
OldActiveSheet:= ActiveSheet;
//If range is in the form 'NewSheet!A1' then first change sheet to 'NewSheet'
if pos('!', Range) > 0 then begin
//Activate the proper sheet...
if not ActivateSheetByName(Copy(Range, 1, pos('!', Range)-1), false) then
raise exception.create('Sheet "'+Copy(Range, 1, pos('!', Range)-1)+'" not present in the document.');
Range:= Copy(Range, pos('!', Range)+1, 999);
end;
result:= ActiveSheet.getCellRangeByName(Range).getCellByPosition(0,0).getFormula;
ActiveSheet:= OldActiveSheet;
end;
end;
end;
procedure TSheetCalc.SetCellTextByName(Range: string; Txt: string);
var OldActiveSheet: variant;
begin
if DocLoaded then begin
if IsExcel then begin
SheetSoftware.Range[Range].formula:= Txt;
end;
if IsOpenOffice then begin
OldActiveSheet:= ActiveSheet;
//If range is in the form 'NewSheet!A1' then first change sheet to 'NewSheet'
if pos('!', Range) > 0 then begin
//Activate the proper sheet...
if not ActivateSheetByName(Copy(Range, 1, pos('!', Range)-1), false) then
raise exception.create('Sheet "'+Copy(Range, 1, pos('!', Range)-1)+'" not present in the document.');
Range:= Copy(Range, pos('!', Range)+1, 999);
end;
ActiveSheet.getCellRangeByName(Range).getCellByPosition(0,0).SetFormula(Txt);
ActiveSheet:= OldActiveSheet;
end;
end;
end;
procedure TSheetCalc.BackgroundColor(row,col: integer; color:TColor);
begin
if DocLoaded then begin
if IsExcel then begin
SheetSoftware.ActiveSheet.Cells[row,col].Interior.Color := color;
end;
if IsOpenOffice then begin
ActiveSheet.getCellByPosition(col-1, row-1).CellBackColor := color;
end;
end;
end;
procedure TSheetCalc.FontSize(row,col,size: integer);
begin
if DocLoaded then begin
if IsExcel then begin
SheetSoftware.ActiveSheet.Cells[row,col].Font.Size := size;
end;
if IsOpenOffice then begin
ActiveSheet.getCellByPosition(col-1, row-1).getText.createTextCursor.CharHeight:= size;
end;
end;
end;
procedure TSheetCalc.Bold(row,col: integer);
const ooBold: integer = 150; //150 = com.sun.star.awt.FontWeight.BOLD
begin
if DocLoaded then begin
if IsExcel then begin
SheetSoftware.ActiveSheet.Cells[row,col].Font.Bold := true;
end;
if IsOpenOffice then begin
ActiveSheet.getCellByPosition(col-1, row-1).getText.createTextCursor.CharWeight:= ooBold;
end;
end;
end;
procedure TSheetCalc.ColumnWidth(col, width: integer); //Width in 1/100 of mm.
begin
if DocLoaded then begin
if IsExcel then begin
//Excel use the width of '0' as the unit, we do an aproximation: Width '0' = 2 mm.
SheetSoftware.ActiveSheet.Cells[1, col].ColumnWidth:= width/100/3;
end;
if IsOpenOffice then begin
ActiveSheet.getCellByPosition(col-1, 0).getColumns.getByIndex(0).Width:= width;
end;
end;
end;
// ***************************
// ** OpenOffice only stuff **
// ***************************
//Change 'C:\File.txt' into 'file:///c:/File.txt' (for OpenOffice OpenURL)
function TSheetCalc.FileName2URL(FileName: string): string;
begin
result:= '';
if LowerCase(copy(FileName,1,8))<>'file:///' then
result:= 'file:///';
result:= result + StringReplace(FileName, '\', '/', [rfReplaceAll, rfIgnoreCase]);
end;
function TSheetCalc.ooCreateValue(ooName: string; ooData: variant): variant;
var
ooReflection: variant;
begin
if IsOpenOffice then begin
ooReflection:= SheetSoftware.createInstance('com.sun.star.reflection.CoreReflection');
ooReflection.forName('com.sun.star.beans.PropertyValue').createObject(result);
result.Name := ooName;
result.Value:= ooData;
end else begin
raise exception.create('ooValue imposible to create, load OpenOffice first!');
end;
end;
procedure TSheetCalc.ooDispatch(ooCommand: string; ooParams: variant);
var
ooDispatcher, ooFrame: variant;
begin
if DocLoaded and IsOpenOffice then begin
if (VarIsEmpty(ooParams) or VarIsNull(ooParams)) then
ooParams:= VarArrayCreate([0, -1], varVariant);
ooFrame:= Document.getCurrentController.getFrame;
ooDispatcher:= SheetSoftware.createInstance('com.sun.star.frame.DispatchHelper');
ooDispatcher.executeDispatch(ooFrame, ooCommand, '', 0, ooParams);
end else begin
raise exception.create('Dispatch imposible, load a OpenOffice doc first!');
end;
end;
function TSheetCalc.ValidateSheetName(Name: string): string;
begin
result := Name;
if trim(result)= '' then result := 'Plan' + IntToStr(CountSheets);
if Pos(':',result) > 0 then result := StringReplace(result,':',' ',[rfReplaceAll]);
if Pos('/',result) > 0 then result := StringReplace(result,'/',' ',[rfReplaceAll]);
if Pos('?',result) > 0 then result := StringReplace(result,'?',' ',[rfReplaceAll]);
if Pos('*',result) > 0 then result := StringReplace(result,'*',' ',[rfReplaceAll]);
if Pos('[',result) > 0 then result := StringReplace(result,'[',' ',[rfReplaceAll]);
if Pos(']',result) > 0 then result := StringReplace(result,']',' ',[rfReplaceAll]);
if Length(result) > 31 then result := Copy(result,1,31);
end;
end.
|
|
|
| Back to top |
|
 |
bitfarmer General User

Joined: 06 May 2004 Posts: 36 Location: Murcia, Spain
|
Posted: Mon Oct 05, 2009 1:37 am Post subject: |
|
|
Hi Romulo, thanxs a lot for posting your enhacements!
I have merged them with my actual version (it was some time ago I update it here, so small changes were only on my version, like OOo V2 compatibility, sorry for this), you can grab it on the edited first post.
It was unfortunate that you changed some object names, I had to revert them to theirs original ones in order to compile on all my existing proyects. I think it was a bad idea, we must keep our code as interchangeable as possible in order to cooperate more easily.
New version V0.95 works OK with OOo V2.x, the changes were small, but tricky to find out what was not working and how to fix it, so I left all changes commented so the info is there if other one is trying to do the same porting to OOo V2.
A new function SaveDocAs(Name: string): boolean; (Added by Massimiliano Gozzi) has been enhaced to allow you to force OOo to save on Excel97 xls format, and internally use URL save mode, so SaveDoc has been reverted to its original form.
Also AddNewSheet has been reverted so it again creates it following the actual sheet, instructions on how to force it to be created at the end of the list have been added so you can chose using it in both flavours (my code needs to create sheets not at the end sometimes).
A function to change color background was on your new code, but was uncommented on the changelist, I added it for you. You are wellcome!
Well, thats all folks!
Sergio Hernandez. |
|
| Back to top |
|
 |
yapt General User

Joined: 30 Jan 2007 Posts: 30
|
Posted: Wed Jan 20, 2010 2:27 am Post subject: |
|
|
Sergio,
where is the last version of this component ?
Thanks and congratulations for your work.
Un saludo.... |
|
| Back to top |
|
 |
bitfarmer General User

Joined: 06 May 2004 Posts: 36 Location: Murcia, Spain
|
Posted: Wed Jan 20, 2010 2:47 am Post subject: |
|
|
Hi yapt, the last version submited of the code is always in the first post of this thread, when something chages, I edit it and copy/paste my actual unit there... if i remember to do it!
I had a newer version on my PC, I had commented the change (small one) and updated the first post, so now you have V0.96 instead of V0.95 |
|
| Back to top |
|
 |
yapt General User

Joined: 30 Jan 2007 Posts: 30
|
Posted: Wed Jan 20, 2010 3:18 am Post subject: |
|
|
Ok Sergio,
muchas gracias. |
|
| Back to top |
|
 |
PauLita Newbie

Joined: 03 Feb 2010 Posts: 2 Location: Vilnius
|
Posted: Wed Feb 03, 2010 10:41 am Post subject: |
|
|
Hi,
can anybody help me to perfom Excel sheet row replication:
for Microsoft Excel it was
| Code: |
Sheet.Rows[r].Copy;
Sheet.Rows[r+1].Insert(xlDown);
|
how this could be done with OpenOffice Calc?
TIA,
Rimvydas |
|
| Back to top |
|
 |
PauLita Newbie

Joined: 03 Feb 2010 Posts: 2 Location: Vilnius
|
Posted: Sat Feb 06, 2010 5:15 am Post subject: |
|
|
Did it. If someone is interested:
| Code: | Programa := CreateOleObject( 'com.sun.star.ServiceManager' );
ooParams := VarArrayCreate([0,0],varVariant);
ooParams[0] := Programa.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
ooView := Document.getCurrentController;
ooFrame := ooView.getFrame;
ooDispatcher := Programa.createInstance('com.sun.star.frame.DispatchHelper');
// copy to clipboard
oRange := Sheet.GetRows.GetByIndex(rl-1);
ooView.Select( oRange );
ooDispatcher.executeDispatch( ooFrame, '.uno:Copy', '', 0, ooParams );
// add one row to the table
Sheet.GetRows.InsertByIndex(rl,1);
// paste from clipboard
oRange := Sheet.GetRows.GetByIndex(rl);
ooView.Select( oRange );
ooDispatcher.executeDispatch( ooFrame, '.uno:Paste', '', 0, ooParams );
|
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|