PageRenderTime 69ms CodeModel.GetById 35ms RepoModel.GetById 0ms app.codeStats 1ms

/UHojaCalc.pas

http://github.com/sergio-hcsoft/Delphi-SpreadSheets
Pascal | 2107 lines | 1395 code | 270 blank | 442 comment | 6 complexity | cc598cd888e381ea1d884cff70ea0927 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. {[w=1-125,e=3,k+] for formatter} //
  2. {[f-] stop formatting}
  3. // *******************************************************
  4. // ** Delphi object for dual SpreadSheet managing using **
  5. // ** Excel/OpenOffice/LibreOffice in a transparent way **
  6. // ** By: Sergio Hernandez (oficina(at)hcsoft.net) **
  7. // ** Version 1.08 18-10-2013 (DDMMYYYY) **
  8. // ** Use it freely, change it, etc. at will. **
  9. // *******************************************************
  10. //Latest version, questions, modifications:
  11. //
  12. // https://github.com/sergio-hcsoft/Delphi-SpreadSheets
  13. // http://user.services.openoffice.org/en/forum/viewtopic.php?f=21&t=47644&p=219641
  14. // http://forum.openoffice.org/en/forum/viewtopic.php?f=21&t=47644&p=288656#p219641
  15. {EXAMPLE OF USE
  16. //Create object: We have two flavours:
  17. //(A) from an existing file...
  18. HCalc:= THojaCalc.create(OpenDialog.FileName, false);
  19. //(B) from a blank document...
  20. HCalc:= THojaCalc.create(thcOpenOffice, true); //OpenOffice doc if possible, please
  21. HCalc.FileName:= 'C:\MyNewDoc'; //Needs a file name before you SaveDoc!
  22. //--end of creation.
  23. HCalc.ActivateSheetByIndex(2); //Activate second sheet
  24. if HCalc.IsActiveSheetProtected then
  25. ShowMessage('2nd sheet of name "'+HCalc.ActiveSheetName+'" IS protected');
  26. //Change a cell value.
  27. IF HCalc.CellText[i,2] = '' THEN HCalc.CellText[i,2] := 'Hello world!';
  28. HCalc.AddNewSheet('New Sheet');
  29. HCalc.PrintDoc;
  30. HCalc.SaveDoc;
  31. HCalc.Free;
  32. }
  33. {TODO LIST:
  34. -PrintActiveSheet is not working for OpenOffice/LibreOffice (even possible?)
  35. }
  36. {CHANGE LOG:
  37. V1.08: (18-10-2013 DD/MM/YYY)
  38. ***************************
  39. ** By user MARCELVK from **
  40. ** forum.openoffice.org **
  41. ***************************
  42. -SetTextCell in OpenOffice/LibreOfice case use .string not setFormula().
  43. -Added properties LastCol and LastRow to get the bounds of used cells.
  44. V1.07: (15-05-2013 DD/MM/YYYY)
  45. -From V1.03, trying to open Excel without Excel installed doesn't try to open
  46. OO instead, just raise an error. Fixed in create().
  47. V1.06: (08-04-2013 DD/MM/YYYY)
  48. *******************
  49. ** Joseph Gordon **
  50. *******************
  51. -New function Orientation(row, Col, Angle) to rotate the text in a cell.
  52. -Auto adjust a column's width using AutoFit(col)
  53. V1.05: (22-02-2013 DDMMYYYY)
  54. -Restored "$INCLUDE Compilers.inc" from V1.03 so code is suitable for other
  55. versions of delphi (Philipe did this works, I just deleted this line ;-).
  56. -Restored 3 commented lines with params. for a code formatter Philipe use. It
  57. has no use for others don't using formatters, but it won't harm us!
  58. V1.04:
  59. -New function StillConnectedToApp() to check if user closed app. manually.
  60. Note: Useful for previewing doc. in OO using code like this:
  61. //
  62. HCalc.Visible:= true;
  63. if HCalc.IsExcel then begin
  64. //Preview of all sheets, one after the user closes the other...
  65. for i:= 1 to HCalc.Document.Sheets.count do
  66. HCalc.Document.Sheets[i].PrintOut(,,,true);
  67. end else begin
  68. //ooDispatcher is just a variant
  69. ooDispatcher:= HCalc.Programa.createInstance('com.sun.star.frame.DispatchHelper');
  70. ooDispatcher.executeDispatch(HCalc.Document.getCurrentController.getFrame, '.uno:PrintPreview', '', 0, VarArrayCreate([0, -1], varVariant));
  71. //OO returns control just after showing, while excel waits for user to close it.
  72. //If you don't wait for user to close preview, you will see just a flash:
  73. while HCalc.StillConnectedToApp() do
  74. sleep(1000);
  75. //User has manually closed the preview window at this point.
  76. end;
  77. //
  78. V1.03:
  79. *****************************
  80. ** Van Coppenolle Philippe **
  81. *****************************
  82. -Reformated code and renamed vars. with more TRY-EXCEPT zones, more robust.
  83. -New function to encapsulate creation of OLE object ConnectToApp()
  84. -Create admits new flag to reuse the last created instance of excel.
  85. -NewDoc admits new flag to add or not a sheet to the new doc (related to the previous one).
  86. -RemoveSheet added in 3 flavours: by index, byname, and all except one name.
  87. -Added list of OLE constant for both Excel and OO so you can use them by name in your code.
  88. -Added FontColor, Underline and HorizontalAlignment properties to cells.
  89. Note: I added some properties so old vars names are still usable:
  90. Document, ActiveSheet and Programa.
  91. V1.02: Creating from a exiting file didn't set the AmericanFormat (thanxs Malte).
  92. V1.01:
  93. ***********************
  94. ** By Malte Tüllmann **
  95. ***********************
  96. -Excel2000/2003 save .xls files in a different way than 2007.
  97. V1.00:
  98. -Saving in Excel2007 will use Excel97 .xls file format instead of .xlsx
  99. V0.99:
  100. -Added a funtion by Alex Smith to set a cell text into italic.
  101. V0.98:
  102. -Added two procedures to easily send a number or a date to a cell position:
  103. SendDate(Row, Col, Date) and SendNumber(Row, Col, Float), if you look at
  104. the code you will notice that this is not so trivial as one could spect.
  105. -I have added (as comments) some useful code found on forums (copy-paste rows)
  106. V0.97:
  107. -Added CellFormula(col, row), similar to CellText, but allows to set a cell
  108. to a number wihout the efect of being considered by excel like a "text that
  109. looks like a number" (doesn't affect OpenOffice). Use it like this:
  110. CellFormula(1,1) := '=A2*23211.66';
  111. Note1: Excel will always spect numbers in this shape: no thousand separator
  112. and dot as decimal separator, regardless of your local configuration.
  113. Note2: Date is also bad interpreted in Excel, in this case you can use
  114. CellText but the date must be in american format: MM/DD/YYYY, if you
  115. use other format, it will try to interpret as an american date and
  116. only if it fails will use your local date format to "decode" it.
  117. V0.96:
  118. -Added PrintSheetsUntil(LastSheetName: string) -only works on excel- to print
  119. out all tabs from 1 until -excluded- the one with the given name in such a
  120. way that only one print job is created instead of one per tab (only way to do
  121. this in previous versions, so converting part of a excel to a single PDF
  122. using a printer like PDFCreator was not posible).
  123. V0.95:
  124. -ActivateSheetByIndex detect imposible index and allows to insert sheet 100 (it will create all necesary sheets)
  125. -SaveDocAs added a second optional parameter for OOo to use Excel97 format (rescued from V0.93 by Rômulo)
  126. -A little stronger ValidateSheetName() (filter away \ and " too).
  127. V0.94:
  128. -OpenOffice V2 compatible (small changes)
  129. -A lot of "try except" to avoid silly errors.
  130. -SaveDocAs(Name: string): boolean; (Added by Massimiliano Gozzi)
  131. -New function FileName2URL(Name) to convert from FileName to URL (OOo SaveDosAs)
  132. -New function ooCreateValue to hide all internals of OOo params creation
  133. V0.93:
  134. ***************************
  135. ** By Rômulo Silva Ramos **
  136. ***************************
  137. -FontSize(Row, Col, Size): change font size in that cell.
  138. -BackgroundColor(row, col: integer; color:TColor);
  139. -Add ValidateSheetName to validate sheet names when adding or renaming a sheet
  140. REVERTED FUNCTIONS (not neccesary in newer version V0.95 anymore)
  141. -Change AddNewSheet to add a new sheet in end at sheet list
  142. *REVERTED IN V0.95*
  143. It creates sheet following the active one, so to add at the end:
  144. ActivateSheetByIndex(CountSheets);
  145. AddNewSheet('Sheet '+IntToStr(CountSheets+1));
  146. -Change in SaveDoc to use SaveAs/StoreAsUrl
  147. *REVERTED V0.95*
  148. Use SaveDocAs(Name, true) for StoreAsUrl in Excel97 format.
  149. V0.92:
  150. -SetActiveSheetName didn't change the name to the right sheet on OpenOffice.
  151. -PrintPreview: New procedure to show up the print preview window.
  152. -Bold(Row, Col): Make bold the text in that cell.
  153. -ColumnWidth(col, width): To change a column width.
  154. V0.91:
  155. -NewDoc: New procedure for creating a blank doc (used in create)
  156. -Create from empty doc adds a blank document and take visibility as parameter.
  157. -New functions ooCreateValue and ooDispatch to clean up the code.
  158. -ActiveSheetName: Now is a read-write property, not a read-only function.
  159. -Visible: Now is a read-write property instead of a create param only.
  160. V0.9:
  161. -Create from empty doc now tries both programs (if OO fails try to use Excel).
  162. -CellTextByName: Didn't work on Excel docs.
  163. }
  164. { PIECES OF CODE FOUND ON FORUMS WORTH COPYING HERE FOR FUTURE USE
  165. -Interesting "copy-paste one row to another" delphi code from PauLita posted
  166. on the OO forum (www.oooforum.org/forum/viewtopic.phtml?t=8878):
  167. OpenOffice version:
  168. Programa := CreateOleObject('com.sun.star.ServiceManager');
  169. ooParams := VarArrayCreate([0,0],varVariant);
  170. ooParams[0] := Programa.Bridge_GetStruct('com.sun.star.beans.PropertyValue');
  171. ooView := Document.getCurrentController;
  172. ooFrame := ooView.getFrame;
  173. ooDispatcher := Programa.createInstance('com.sun.star.frame.DispatchHelper');
  174. // copy to clipboard
  175. oRange := Sheet.GetRows.GetByIndex(rl-1);
  176. ooView.Select( oRange );
  177. ooDispatcher.executeDispatch( ooFrame, '.uno:Copy', '', 0, ooParams );
  178. // add one row to the table
  179. Sheet.GetRows.InsertByIndex(rl,1);
  180. // paste from clipboard
  181. oRange := Sheet.GetRows.GetByIndex(rl);
  182. ooView.Select( oRange );
  183. ooDispatcher.executeDispatch( ooFrame, '.uno:Paste', '', 0, ooParams );
  184. Excel version:
  185. Sheet.Rows[r].Copy;
  186. Sheet.Rows[r+1].Insert(xlDown);
  187. }
  188. {[f?] restore formatting}
  189. UNIT UHojaCalc;
  190. //Find this file searching on google, or just try here:
  191. // https://code.google.com/p/virtual-treeview/source/browse/trunk/Common/Compilers.inc?r=235
  192. {$INCLUDE Compilers.inc}
  193. INTERFACE
  194. USES
  195. Windows,
  196. {$IFDEF COMPILER_6_UP}
  197. Variants,
  198. {$ELSE}
  199. {$ENDIF}
  200. SysUtils, ComObj, Classes, Graphics, Controls;
  201. CONST
  202. {--------------------------------------------------------------------------------}
  203. { Excel constants ( OLE support ) }
  204. { http://www.koders.com/noncode/fid793D4B61A1DF009ACD6544001B50528A598EB275.aspx }
  205. {--------------------------------------------------------------------------------}
  206. { XlApplicationInternational }
  207. xlCountryCode = 1;
  208. xlCountrySetting = 2;
  209. xlDecimalSeparator = 3;
  210. xlThousandsSeparator = 4;
  211. xlListSeparator = 5;
  212. xlUpperCaseRowLetter = 6;
  213. xlUpperCaseColumnLetter = 7;
  214. xlLowerCaseRowLetter = 8;
  215. xlLowerCaseColumnLetter = 9;
  216. xlLeftBracket = 10;
  217. xlRightBracket = 11;
  218. xlLeftBrace = 12;
  219. xlRightBrace = 13;
  220. xlColumnSeparator = 14;
  221. xlRowSeparator = 15;
  222. xlAlternateArraySeparator = 16; //(&H10)
  223. xlDateSeparator = 17; //(&H11)
  224. xlTimeSeparator = 18; //(&H12)
  225. xlYearCode = 19; //(&H13)
  226. xlMonthCode = 20; //(&H14)
  227. xlDayCode = 21; //(&H15)
  228. xlHourCode = 22; //(&H16)
  229. xlMinuteCode = 23; //(&H17)
  230. xlSecondCode = 24; //(&H18)
  231. xlCurrencyCode = 25; //(&H19)
  232. xlGeneralFormatName = 26; //(&H1A)
  233. xlCurrencyDigits = 27; //(&H1B)
  234. xlCurrencyNegative = 28; //(&H1C)
  235. xlNocurrencyDigits = 29; //(&H1D)
  236. xlMonthNameChars = 30; //(&H1E)
  237. xlWeekdayNameChars = 31; //(&H1F)
  238. xlDateOrder = 32; //(&H20)
  239. xl24HourClock = 33; //(&H21)
  240. xlNonEnglishFunctions = 34; //(&H22)
  241. xlMetric = 35; //(&H23)
  242. xlCurrencySpaceBefore = 36; //(&H24)
  243. xlCurrencyBefore = 37; //(&H25)
  244. xlCurrencyMinusSign = 38; //(&H26)
  245. xlCurrencyTrailingZeros = 39; //(&H27)
  246. xlCurrencyLeadingZeros = 40; //(&H28)
  247. xlMonthLeadingZero = 41; //(&H29)
  248. xlDayLeadingZero = 42; //(&H2A)
  249. xl4DigitYears = 43; //(&H2B)
  250. xlMDY = 44; //(&H2C)
  251. xlTimeLeadingZero = 45; //(&H2D)
  252. xlCellTypeLastCell = 11;
  253. { typedef enum XlVAlign }
  254. xlVAlignBottom = -4107;
  255. xlVAlignCenter = -4108;
  256. xlVAlignDistributed = -4117;
  257. xlVAlignJustify = -4130;
  258. xlVAlignTop = -4160;
  259. { typedef enum XlHAlign }
  260. xlHAlignCenter = - 4108;
  261. xlHAlignCenterAcrossSelection = 7;
  262. xlHAlignDistributed = -4117;
  263. xlHAlignFill = 5;
  264. xlHAlignGeneral = 1;
  265. xlHAlignJustify = -4130;
  266. xlHAlignLeft = -4131;
  267. xlHAlignRight = - 4152;
  268. { XlSheetType }
  269. xlChart = - 4109;
  270. xlDialogSheet = - 4116;
  271. xlExcel4IntlMacroSheet = 4;
  272. xlExcel4MacroSheet = 3;
  273. xlWorksheet = - 4167;
  274. { XlWBATemplate }
  275. xlWBATChart = - 4109;
  276. xlWBATExcel4IntlMacroSheet = 4;
  277. xlWBATExcel4MacroSheet = 3;
  278. xlWBATWorksheet = - 4167;
  279. { XlUnderlineStyle }
  280. xlUnderlineStyleNone = - 4142; // (&HFFFFEFD2)
  281. xlUnderlineStyleSingle = 2;
  282. xlUnderlineStyleDouble = - 4119; // (&HFFFFEFE9)
  283. xlUnderlineStyleSingleAccounting = 4;
  284. xlUnderlineStyleDoubleAccounting = 5;
  285. {------------------------------------------------------------------------------}
  286. { OpenOffice constants ( OLE support ) }
  287. {------------------------------------------------------------------------------}
  288. { NumberFormat, see }
  289. { http://www.openoffice.org/api/docs/common/ref/com/sun/star/util/NumberFormat.html }
  290. nfALL = 0; // Description selects all number formats.
  291. nfDEFINED = 1; // Description selects only user-defined number formats.
  292. nfDATE = 2; // Description selects date formats.
  293. nfTIME = 4; // Description selects time formats.
  294. nfCURRENCY = 8; // Description selects currency formats.
  295. nfNUMBER = 16; // Description selects decimal number formats.
  296. nfSCIENTIFIC = 32; // Description selects scientific number formats.
  297. nfFRACTION = 64; // Description selects number formats for fractions.
  298. nfPERCENT = 128; // Description selects percentage number formats.
  299. nfTEXT = 256; // Description selects text number formats.
  300. nfDATETIME = 6; // Description selects number formats which contain date and time.
  301. nfLOGICAL = 1024; // Description selects boolean number formats.
  302. nfUNDEFINED = 2048; // Description is used as a return value if no format exists.
  303. TYPE
  304. { thcError: Tried to open but both fails }
  305. { thcNone: Haven't tried still to open any }
  306. TTipoHojaCalc =
  307. (thcError, thcNone, thcExcel, thcOpenOffice);
  308. TOoUnderlineStyle =
  309. (ulNone, // = 0
  310. ulSingle, // = 1
  311. ulDouble, // = 2
  312. ulDotted, // = 3
  313. ulUndef4, // = 4
  314. ulDash, // = 5
  315. ulLongDash, // = 6
  316. ulDashDot, // = 7
  317. ulDashDotDot, // = 8
  318. ulWave, // = 9
  319. ulSmallWave, // = 10
  320. ulDoubleWave, // = 11
  321. ulBold, // = 12
  322. ulBoldDotted, // = 13
  323. ulBoldDash, // = 14
  324. ulBoldLongDash, // = 15
  325. ulBoldDashDot, // = 16
  326. ulBoldDashDotDot, // = 17
  327. ulBold_wave // = 18
  328. );
  329. THojaCalc = CLASS (TObject)
  330. PRIVATE
  331. m_bVisible: boolean;
  332. m_bKeepAlive: boolean;
  333. m_eTipo: TTipoHojaCalc; //Which program was used to manage the doc?
  334. m_strFileName: string; //In windows FileName format C:\MyDoc.XXX
  335. m_bReUseExisting: boolean; // re-use an existing instance of the program
  336. m_bFirstAddedSheet: boolean; // becomes false after adding a new sheet
  337. m_vActiveSheet: variant; //Active sheet.
  338. m_vPrograma: variant; //Excel or OpenOfice instance created.
  339. m_vDocument: variant; //Document opened.
  340. {$IFDEF COMPILER_7_UP}
  341. m_AmericanFormat: TFormatSettings;
  342. {$ENDIF COMPILER_7_UP} //
  343. //Object internals...
  344. FUNCTION ConnectToApp (eMyTipo, eReqTipo: TTipoHojaCalc; bReUseExisting: boolean): TTipoHojaCalc;
  345. //Program loaded stuff...
  346. PROCEDURE LoadProg;
  347. PROCEDURE CloseProg;
  348. FUNCTION GetProgLoaded: boolean;
  349. PROCEDURE NewDoc (bAddNewSheet: boolean);
  350. PROCEDURE LoadDoc;
  351. PROCEDURE CloseDoc;
  352. FUNCTION GetDocLoaded: boolean;
  353. FUNCTION GetIsExcel: boolean;
  354. FUNCTION GetIsOpenOffice: boolean;
  355. PROCEDURE SetVisible (v: boolean); //
  356. //Sheets stuff..
  357. FUNCTION GetCountSheets: integer;
  358. FUNCTION GetActiveSheetName: string;
  359. PROCEDURE SetActiveSheetName (strNewName: string); //
  360. function GetLastRow: integer;
  361. function GetLastCol: integer;
  362. //Cells stuff...
  363. //General input/output of cell content:
  364. FUNCTION GetCellText (row, col: integer): string;
  365. PROCEDURE SetCellText (row, col: integer; strTxt: string);
  366. FUNCTION GetCellFormula (row, col: integer): string;
  367. PROCEDURE SetCellFormula (row, col: integer; strTxt: string);
  368. FUNCTION GetCellTextByName (strRange: string): string;
  369. PROCEDURE SetCellTextByName (strRange: string; strTxt: string); //
  370. //OpenOffice only stuff...
  371. FUNCTION FileName2URL (strFileName: string): string;
  372. PROCEDURE ooDispatch (strOoCommand: string; vOoParams: variant);
  373. FUNCTION ooCreateValue (strOoName: string; vOoData: variant): variant; //
  374. //Aux functions
  375. FUNCTION ValidateSheetName (strName: string): string;
  376. PUBLIC
  377. m_vDeskTop: variant; //OpenOffice desktop reference.
  378. //Object internals...
  379. CONSTRUCTOR Create (strName: string; bMakeVisible: boolean; bReUseExisting: boolean = false); overload;
  380. CONSTRUCTOR Create (eMyTipo: TTipoHojaCalc; bMakeVisible: boolean; bReUseExisting: boolean = false); overload;
  381. DESTRUCTOR Destroy; override; //
  382. FUNCTION StillConnectedToApp: boolean;
  383. //Program loaded stuff...
  384. FUNCTION SaveDoc: boolean;
  385. FUNCTION SaveDocAs (strName: string; bAsExcel97: boolean = false): boolean;
  386. FUNCTION PrintDoc: boolean;
  387. PROCEDURE ShowPrintPreview;
  388. PROPERTY Programa: variant read m_vPrograma write m_vPrograma;
  389. PROPERTY ProgLoaded: boolean read GetProgLoaded;
  390. PROPERTY Document: variant read m_vDocument write m_vDocument;
  391. PROPERTY DocLoaded: boolean read GetDocLoaded;
  392. PROPERTY IsExcel: boolean read GetIsExcel;
  393. PROPERTY IsOpenOffice: boolean read GetIsOpenOffice;
  394. PROPERTY Visible: boolean read m_bVisible write SetVisible;
  395. PROPERTY KeepAlive: boolean read m_bKeepAlive write m_bKeepAlive;
  396. //Sheets stuff...
  397. FUNCTION ActivateSheetByIndex (nIndex: integer): boolean;
  398. FUNCTION ActivateSheetByName (strSheetName: string; bCaseSensitive: boolean): boolean;
  399. FUNCTION IsActiveSheetProtected: boolean;
  400. FUNCTION PrintActiveSheet: boolean;
  401. FUNCTION PrintSheetsUntil (strLastSheetName: string): boolean;
  402. PROCEDURE AddNewSheet (strNewName: string; bRemoveDummySheets: boolean = false);
  403. PROCEDURE RemoveSheetByName (strOldName: string);
  404. PROCEDURE RemoveSheetByIndex (nIndex: integer);
  405. PROCEDURE RemoveAllSheetsExcept (strOldName: string; bCaseSensitive: boolean);
  406. PROPERTY eTipo: TTipoHojaCalc read m_eTipo {write m_eTipo};
  407. PROPERTY FileName: string read m_strFileName write m_strFileName;
  408. PROPERTY CountSheets: integer read GetCountSheets;
  409. PROPERTY ActiveSheet: variant read m_vActiveSheet write m_vActiveSheet;
  410. PROPERTY ActiveSheetName: string read GetActiveSheetName write SetActiveSheetName;
  411. PROPERTY FirstAddedSheet: boolean read m_bFirstAddedSheet; //
  412. property LastRow: integer read GetLastRow;
  413. property LastCol: integer read GetLastCol;
  414. //Cells stuff...
  415. //Sending numbers and date to a cell, the easy way:
  416. PROCEDURE SendNumber (row, col: integer; v: double);
  417. PROCEDURE SendDate (row, col: integer; v: TDate); //Properties:
  418. PROCEDURE Bold (row, col: integer);
  419. PROCEDURE Italic (row, col: integer);
  420. PROCEDURE Underline (row, col: integer; eOoUnderlineStyle: TOoUnderlineStyle);
  421. PROCEDURE FontColor (row, col: integer; color: TColor);
  422. PROCEDURE BackgroundColor (row, col: integer; color: TColor);
  423. PROCEDURE FontSize (row, col, size: integer);
  424. PROCEDURE HorizontalAlignment (row, col: integer; ha: TAlignment);
  425. PROCEDURE ColumnWidth (col, width: integer); //Width in 1/100 of mm.
  426. PROCEDURE NumberFormat (col, width: integer; strNumberFormat: string);
  427. PROCEDURE Orientation(row,Col: integer; Angle: integer);
  428. PROCEDURE AutoFit(col: integer); //AutoFix/OptimumWidth
  429. //Accesing to the cell content:
  430. PROPERTY CellText[f, c: integer]: string read GetCellText write SetCellText;
  431. PROPERTY CellFormula[f, c: integer]: string read GetCellFormula write SetCellFormula;
  432. PROPERTY CellTextByName[Range: string]: string read GetCellTextByName write SetCellTextByName;
  433. //Aux functions
  434. FUNCTION SwapColor (nColor: TColor): TColor;
  435. END {THojaCalc};
  436. IMPLEMENTATION //
  437. CONST
  438. strOleExcel = 'Excel.Application';
  439. strOleOpenOffice = 'com.sun.star.ServiceManager';
  440. strOleOoDesktop = 'com.sun.star.frame.Desktop';
  441. { ************************ }
  442. { ** Create and destroy ** }
  443. { ************************ }
  444. CONSTRUCTOR THojaCalc.Create (eMyTipo: TTipoHojaCalc; bMakeVisible: boolean; bReUseExisting: boolean = false);
  445. { Create with an empty doc of requested type (use thcExcel or thcOpenOffice) }
  446. { Remember to define FileName before calling to SaveDoc }
  447. VAR
  448. nTryal: integer;
  449. BEGIN
  450. m_bKeepAlive := false; //
  451. //Close all opened things first...
  452. CloseDoc;
  453. CloseProg; //
  454. //I will try to open twice, so if Excel fails, OpenOffice is used instead
  455. m_eTipo := thcNone;
  456. m_bReUseExisting := bReUseExisting;
  457. FOR nTryal := 1 TO 2 DO
  458. BEGIN //
  459. //Try to open Excel...
  460. m_eTipo := ConnectToApp(eMyTipo, thcExcel, bReUseExisting);
  461. IF m_eTipo = thcExcel THEN
  462. break;
  463. //Try to open OpenOffice...
  464. m_eTipo := ConnectToApp(eMyTipo, thcOpenOffice, bReUseExisting);
  465. IF m_eTipo = thcOpenOffice THEN
  466. break;
  467. //Unlucky? Then let it use whatever it finds on the second try:
  468. eMyTipo:= thcNone;
  469. END {FOR}; //
  470. { Was it able to open any of them? }
  471. IF eTipo = thcNone THEN
  472. BEGIN
  473. m_eTipo := thcError;
  474. RAISE Exception.Create('THojaCalc.create failed, may be no Office is installed?');
  475. END {IF}; //
  476. { Add a blank document... }
  477. m_bVisible := bMakeVisible;
  478. NewDoc(NOT m_bReUseExisting); // Do NOT add a new sheet an existing WB must be re-used
  479. //Create an American format to use when sending numbers or dates to excel
  480. {$IFDEF COMPILER_12_UP}
  481. m_AmericanFormat := TFormatSettings.Create(Windows.LOCALE_NEUTRAL);
  482. {$ELSE}
  483. {$IFDEF COMPILER_8_UP}
  484. GetLocaleFormatSettings(Windows.LOCALE_NEUTRAL, m_AmericanFormat);
  485. {$ELSE}
  486. {$ENDIF}
  487. {$ENDIF}
  488. {$IFDEF COMPILER_7_UP}
  489. GetLocaleFormatSettings( 0, m_AmericanFormat);
  490. m_AmericanFormat.ThousandSeparator := ',';
  491. m_AmericanFormat.DecimalSeparator := '.';
  492. m_AmericanFormat.ShortDateFormat := 'mm/dd/yyyy';
  493. {$ELSE}
  494. //Will be updated where needed, as they must be saved before and restored afterwards
  495. //SysUtils.ThousandSeparator := ',';
  496. //SysUtils.DecimalSeparator := '.';
  497. //SysUtils.ShortDateFormat := 'mm/dd/yyyy';
  498. {$ENDIF}
  499. END {THojaCalc.Create};
  500. CONSTRUCTOR THojaCalc.Create (strName: string; bMakeVisible: boolean; bReUseExisting: boolean = false);
  501. BEGIN
  502. m_eTipo := thcNone; //
  503. //Store values...
  504. m_strFileName := strName;
  505. m_bVisible := bMakeVisible; //
  506. //Create an American format to use when sending numbers or dates to excel
  507. {$IFDEF COMPILER_12_UP}
  508. m_AmericanFormat := TFormatSettings.Create(Windows.LOCALE_NEUTRAL);
  509. {$ELSE}
  510. {$IFDEF COMPILER_8_UP}
  511. GetLocaleFormatSettings(Windows.LOCALE_NEUTRAL, m_AmericanFormat);
  512. {$ELSE}
  513. {$ENDIF}
  514. {$ENDIF}
  515. {$IFDEF COMPILER_7_UP}
  516. //Will be updated where needed, as they must be saved before and restored afterwards
  517. //SysUtils.ThousandSeparator := ',';
  518. //SysUtils.DecimalSeparator := '.';
  519. //SysUtils.ShortDateFormat := 'mm/dd/yyyy';
  520. {$ELSE}
  521. {$ENDIF} //
  522. //Open program and document...
  523. LoadProg;
  524. LoadDoc;
  525. END {THojaCalc.Create};
  526. FUNCTION THojaCalc.ConnectToApp (eMyTipo, eReqTipo: TTipoHojaCalc; bReUseExisting: boolean): TTipoHojaCalc;
  527. VAR
  528. strOleName: string;
  529. BEGIN
  530. result := thcNone;
  531. CASE eReqTipo OF
  532. thcExcel:
  533. strOleName := strOleExcel;
  534. thcOpenOffice:
  535. strOleName := strOleOpenOffice;
  536. ELSE
  537. RAISE Exception.Create('THojaCalc.ConnectToApp failed, invalid requested type');
  538. END {CASE};
  539. IF (eMyTipo = thcNone) OR (eMyTipo = eReqTipo) THEN
  540. BEGIN
  541. IF bReUseExisting THEN
  542. TRY
  543. TRY
  544. m_vPrograma := GetActiveOleObject(strOleName);
  545. EXCEPT
  546. END {TRY};
  547. FINALLY
  548. END {TRY};
  549. IF NOT ProgLoaded THEN
  550. TRY
  551. TRY
  552. m_vPrograma := CreateOleObject(strOleName);
  553. EXCEPT
  554. END {TRY};
  555. FINALLY
  556. END {TRY};
  557. IF ProgLoaded THEN
  558. result := eReqTipo;
  559. END {IF};
  560. END {THojaCalc.ConnectToApp};
  561. //After you call a preview, for instance, you can check if the user closed the doc.
  562. FUNCTION THojaCalc.StillConnectedToApp: boolean;
  563. //VAR
  564. // strOleName: string;
  565. // tmp_Programa: variant;
  566. BEGIN
  567. result := false;
  568. CASE m_eTipo OF
  569. thcExcel:
  570. TRY
  571. GetActiveOleObject(strOleExcel);
  572. result:= true;
  573. EXCEPT
  574. END {TRY};
  575. thcOpenOffice:
  576. TRY
  577. m_vDocument.getCurrentController.getFrame.getContainerWindow;
  578. result:= true;
  579. EXCEPT
  580. END {TRY};
  581. ELSE
  582. exit;
  583. END; {CASE};
  584. TRY
  585. FINALLY
  586. END {TRY};
  587. //result:= NOT (VarIsEmpty(tmp_Programa) OR VarIsNull(tmp_Programa));
  588. END {THojaCalc.StillConnectedToApp};
  589. DESTRUCTOR THojaCalc.Destroy;
  590. BEGIN
  591. IF NOT m_bKeepAlive THEN
  592. TRY
  593. TRY
  594. CloseDoc;
  595. EXCEPT
  596. END;
  597. FINALLY
  598. CloseProg;
  599. END {IF};
  600. INHERITED;
  601. END {THojaCalc.Destroy};
  602. { ************************* }
  603. { ** Loading the program ** }
  604. { ** Excel or OpenOffice ** }
  605. { ************************* }
  606. PROCEDURE THojaCalc.LoadProg;
  607. BEGIN
  608. IF ProgLoaded THEN
  609. CloseProg;
  610. m_eTipo := thcNone;
  611. IF (UpperCase(ExtractFileExt(m_strFileName)) = '.XLS') THEN
  612. BEGIN //Excel is the primary choice...
  613. m_eTipo := ConnectToApp(thcNone, thcExcel, m_bReUseExisting);
  614. END {IF}; //
  615. //Not lucky with Excel? Another filetype? Let's go with OpenOffice...
  616. IF eTipo = thcNone THEN
  617. BEGIN //Try with OpenOffice...
  618. m_eTipo := ConnectToApp(thcNone, thcOpenOffice, m_bReUseExisting);
  619. END {IF}; //
  620. //Still no program loaded?
  621. IF NOT ProgLoaded THEN
  622. BEGIN
  623. m_eTipo := thcError;
  624. RAISE Exception.Create('THojaCalc.create failed, may be no Office is installed?');
  625. END {IF};
  626. END {THojaCalc.LoadProg};
  627. PROCEDURE THojaCalc.CloseProg;
  628. BEGIN
  629. IF NOT Visible THEN
  630. CloseDoc;
  631. IF ProgLoaded THEN
  632. BEGIN
  633. TRY
  634. IF IsExcel THEN
  635. m_vPrograma.Quit; //
  636. //Next line made OO V2 not to work anymore as the next call to
  637. //CreateOleObject(strOleOpenOffice) failed.
  638. //IF IsOpenOffice THEN Programa.Dispose;
  639. m_vPrograma := Unassigned;
  640. FINALLY
  641. END {TRY};
  642. END {IF};
  643. m_eTipo := thcNone;
  644. END {THojaCalc.CloseProg};
  645. FUNCTION THojaCalc.GetProgLoaded: boolean;
  646. { Is there any prog loaded? Which one? }
  647. BEGIN
  648. result := NOT (VarIsEmpty(m_vPrograma) OR VarIsNull(m_vPrograma));
  649. END {THojaCalc.GetProgLoaded};
  650. FUNCTION THojaCalc.GetIsExcel: boolean;
  651. BEGIN
  652. result := (m_eTipo = thcExcel);
  653. END {THojaCalc.GetIsExcel};
  654. FUNCTION THojaCalc.GetIsOpenOffice: boolean;
  655. BEGIN
  656. result := (m_eTipo = thcOpenOffice);
  657. END {THojaCalc.GetIsOpenOffice};
  658. { ************************ }
  659. { ** Loading a document ** }
  660. { ************************ }
  661. PROCEDURE THojaCalc.NewDoc (bAddNewSheet: boolean);
  662. VAR
  663. vOoParams: variant;
  664. AttrPtr: pointer;
  665. BEGIN //
  666. //Is the program running? (Excel or OpenOffice)
  667. IF NOT ProgLoaded THEN
  668. RAISE Exception.Create('No program loaded for the new document.'); //
  669. //Is there a doc already loaded?
  670. CloseDoc;
  671. m_vDeskTop := Unassigned; //
  672. //OK, now try to create the doc...
  673. IF IsExcel THEN
  674. BEGIN
  675. m_vDocument := Unassigned;
  676. IF m_bReUseExisting THEN
  677. BEGIN
  678. m_vDocument := m_vPrograma.ActiveWorkBook;
  679. AttrPtr := TVarData(m_vDocument).VDispatch;
  680. IF NOT assigned(AttrPtr) THEN
  681. m_vDocument := Unassigned;
  682. END {IF};
  683. IF (VarIsEmpty(m_vDocument) OR VarIsNull(m_vDocument))
  684. THEN // no WorkBook present --> create a new one, including sheets
  685. BEGIN
  686. m_vDocument := m_vPrograma.WorkBooks.Add;
  687. m_bFirstAddedSheet := true;
  688. END {IF}
  689. ELSE // Workbook present --> create only a new sheet
  690. BEGIN
  691. IF bAddNewSheet THEN
  692. m_vActiveSheet := m_vDocument.Sheets.Add;
  693. m_bFirstAddedSheet := false;
  694. END {ELSE};
  695. m_vPrograma.Visible := Visible;
  696. m_vDocument := m_vPrograma.ActiveWorkBook;
  697. m_vActiveSheet := m_vDocument.ActiveSheet;
  698. END {IF};
  699. IF IsOpenOffice THEN
  700. BEGIN
  701. m_vDesktop := m_vPrograma.CreateInstance(strOleOoDesktop); //
  702. //Optional parameters (visible)...
  703. vOoParams := VarArrayCreate([0, 0], varVariant);
  704. vOoParams[0] := ooCreateValue('Hidden', NOT Visible); //
  705. //Create the document...
  706. m_vDocument := m_vDesktop.LoadComponentFromURL('private:factory/scalc', '_blank', 0, vOoParams);
  707. ActivateSheetByIndex(1);
  708. m_bFirstAddedSheet := true;
  709. END {IF};
  710. //{ Keep only 1 sheet in the workbook }
  711. // WHILE CountSheets > 1 DO
  712. // RemoveSheetByIndex(2);
  713. END {THojaCalc.NewDoc};
  714. PROCEDURE THojaCalc.LoadDoc;
  715. VAR
  716. vOoParams: variant;
  717. BEGIN
  718. IF m_strFileName = '' THEN
  719. exit; //
  720. //Is the program running? (Excel or OpenOffice)
  721. IF NOT ProgLoaded THEN
  722. LoadProg; //
  723. //Is there a doc already loaded?
  724. CloseDoc;
  725. m_vDeskTop := Unassigned; //
  726. //OK, now try to open the doc...
  727. IF IsExcel THEN
  728. BEGIN
  729. m_vPrograma.WorkBooks.Open(m_strFileName, 3);
  730. m_vPrograma.Visible := Visible;
  731. m_vDocument := m_vPrograma.ActiveWorkBook;
  732. m_vActiveSheet := m_vDocument.ActiveSheet;
  733. END {IF};
  734. IF IsOpenOffice THEN
  735. BEGIN
  736. m_vDesktop := m_vPrograma.CreateInstance(strOleOoDesktop); //
  737. //Optional parameters (visible)...
  738. vOoParams := VarArrayCreate([0, 0], varVariant); //
  739. //Next line stop working OK on OOo V2: Created blind, always blind!
  740. //so now it is create as visible, then set to non visible if requested
  741. //vOoParams[0] := ooCreateValue('Hidden', not Visible);
  742. vOoParams[0] := ooCreateValue('Hidden', false); //Create as visible, then make it not visible if necesary
  743. //Open the document...
  744. m_vDocument := m_vDesktop.LoadComponentFromURL(FileName2URL(m_strFileName), '_blank', 0, vOoParams);
  745. m_vActiveSheet := ActivateSheetByIndex(1); //
  746. //If has to be non visible, set it now...
  747. IF NOT visible THEN
  748. m_vDocument.getCurrentController.getFrame.getContainerWindow.setVisible(false);
  749. END {IF};
  750. IF m_eTipo = thcNone THEN
  751. RAISE Exception.Create('Cannot read file "' + m_strFileName + '" because the needed program is not available.');
  752. END {THojaCalc.LoadDoc};
  753. FUNCTION THojaCalc.SaveDoc: boolean;
  754. BEGIN
  755. result := false;
  756. IF DocLoaded THEN
  757. BEGIN
  758. IF IsExcel THEN
  759. BEGIN
  760. m_vDocument.Save;
  761. result := true;
  762. END {IF};
  763. IF IsOpenOffice THEN
  764. BEGIN
  765. m_vDocument.Store;
  766. result := true;
  767. END {IF};
  768. END {IF};
  769. END {THojaCalc.SaveDoc};
  770. FUNCTION THojaCalc.SaveDocAs (strName: string; bAsExcel97: boolean = false): boolean;
  771. { Function added by Massimiliano Gozzi on V0.92 }
  772. { AsEXcel97 taken form V0.93 by Rômulo Silva Ramos }
  773. { Saving as .xls on Excel 2000/2003 trick by Malte Tüllmann on V1.01 }
  774. VAR
  775. vOoParams: variant;
  776. exVersion: Extended;
  777. saveThousandSeparator, saveDecimalSeparator: char;
  778. BEGIN
  779. result := false;
  780. IF DocLoaded
  781. THEN
  782. BEGIN
  783. IF IsExcel THEN
  784. BEGIN
  785. {$IFDEF COMPILER_7_UP}
  786. exVersion := StrToFloat(m_vPrograma.Application.Version, m_AmericanFormat);
  787. {$ELSE COMPILER_7_UP}
  788. saveThousandSeparator := SysUtils.ThousandSeparator;
  789. saveDecimalSeparator := SysUtils.DecimalSeparator;
  790. SysUtils.ThousandSeparator := ',';
  791. SysUtils.DecimalSeparator := '.';
  792. exVersion := StrToFloat(m_vPrograma.Application.Version);
  793. SysUtils.ThousandSeparator := saveThousandSeparator;
  794. SysUtils.DecimalSeparator := saveDecimalSeparator;
  795. {$ENDIF COMPILER_7_UP}
  796. IF (exVersion < 12)
  797. THEN //
  798. //Before Excel 2007 this was the method to force SaveAs Excel97 .xls
  799. //by Malte Tüllmann on V1.01
  800. m_vDocument.Saveas(strName, - 4143, EmptyParam, EmptyParam, EmptyParam, EmptyParam)
  801. ELSE //
  802. // From Excel 2003 this is the way to force .xls file format (excel8)
  803. // for back compatibility with older excel version and OO.
  804. //
  805. // 51 = xlOpenXMLWorkbook (without macro's in 2007-2010, xlsx)
  806. // 52 = xlOpenXMLWorkbookMacroEnabled (with or without macro's in 2007-2010, xlsm)
  807. // 50 = xlExcel12 (Excel Binary Workbook in 2007-2010 with or without macro's, xlsb)
  808. // 56 = xlExcel8 (97-2003 format in Excel 2007-2010, xls)
  809. // More on this here: http://www.rondebruin.nl/saveas.htm
  810. m_vDocument.Saveas(strName, 56);
  811. m_strFileName := strName;
  812. result := true;
  813. END {IF};
  814. IF IsOpenOffice THEN
  815. BEGIN //
  816. //I may need 1 or 2 params...
  817. IF bAsExcel97
  818. THEN
  819. vOoParams := VarArrayCreate([0, 1], varVariant)
  820. ELSE
  821. vOoParams := VarArrayCreate([0, 0], varVariant); //
  822. //First one for prompting on overwrite (good idea!)
  823. vOoParams[0] := ooCreateValue('Overwrite', false); //
  824. //Optionally tell OpenOffie to use Excel97 .xls format
  825. IF bAsExcel97 THEN
  826. vOoParams[1] := ooCreateValue('FilterName', 'MS Excel 97'); //
  827. //Do the save!
  828. m_vDocument.StoreAsUrl(FileName2URL(strName), vOoParams);
  829. m_strFileName := strName;
  830. result := true;
  831. END {IF};
  832. END {IF};
  833. END {THojaCalc.SaveDocAs};
  834. FUNCTION THojaCalc.PrintDoc: boolean;
  835. { Print the Doc... }
  836. VAR
  837. vOoParams: variant;
  838. BEGIN
  839. result := false;
  840. IF DocLoaded THEN
  841. BEGIN
  842. IF IsExcel THEN
  843. BEGIN
  844. m_vDocument.PrintOut;
  845. result := true;
  846. END {IF};
  847. IF IsOpenOffice THEN
  848. BEGIN //
  849. //NOTE: OpenOffice will print all sheets with Printable areas, but if no
  850. //printable areas are defined in the doc, it will print all entire sheets.
  851. //Optional parameters (wait until fully sent to printer)...
  852. vOoParams := VarArrayCreate([0, 0], varVariant);
  853. vOoParams[0] := ooCreateValue('Wait', true);
  854. m_vDocument.Print(vOoParams);
  855. result := true;
  856. END {IF};
  857. END {IF};
  858. END {THojaCalc.PrintDoc};
  859. PROCEDURE THojaCalc.ShowPrintPreview;
  860. BEGIN
  861. IF DocLoaded THEN
  862. BEGIN //
  863. //Force visibility of the doc...
  864. Visible := true;
  865. IF IsExcel THEN
  866. m_vDocument.PrintOut(,,, true);
  867. IF IsOpenOffice THEN
  868. ooDispatch('.uno:PrintPreview', Unassigned);
  869. END {IF};
  870. END {THojaCalc.ShowPrintPreview};
  871. PROCEDURE THojaCalc.SetVisible (v: boolean);
  872. BEGIN
  873. IF DocLoaded AND (v <> m_bVisible) THEN
  874. BEGIN
  875. IF IsExcel THEN
  876. m_vPrograma.Visible := v;
  877. IF IsOpenOffice THEN
  878. m_vDocument.getCurrentController.getFrame.getContainerWindow.setVisible(v);
  879. m_bVisible := v;
  880. END {IF};
  881. END {THojaCalc.SetVisible};
  882. PROCEDURE THojaCalc.CloseDoc;
  883. BEGIN
  884. IF DocLoaded THEN
  885. BEGIN //
  886. //Close it...
  887. TRY
  888. IF IsOpenOffice THEN
  889. TRY
  890. m_vDocument.Dispose;
  891. EXCEPT
  892. END;
  893. IF IsExcel THEN
  894. TRY
  895. m_vDocument.close;
  896. EXCEPT
  897. END;
  898. FINALLY
  899. END {TRY}; //
  900. //Clean up both "pointer"...
  901. m_vDocument := Null;
  902. m_vActiveSheet := Null;
  903. END {IF};
  904. END {THojaCalc.CloseDoc};
  905. FUNCTION THojaCalc.GetDocLoaded: boolean;
  906. VAR
  907. AttrPtr: Pointer;
  908. BEGIN
  909. IF IsExcel AND m_bVisible THEN
  910. BEGIN
  911. m_vPrograma := GetActiveOleObject(strOleExcel);
  912. IF VarIsEmpty(m_vPrograma) OR VarIsNull(m_vPrograma)
  913. THEN
  914. m_vDocument := Unassigned
  915. ELSE
  916. BEGIN
  917. m_vDocument := m_vPrograma.ActiveWorkBook;
  918. AttrPtr := TVarData(m_vDocument).VDispatch;
  919. IF NOT assigned(AttrPtr) THEN
  920. m_vDocument := Unassigned
  921. END {ELSE};
  922. END {IF};
  923. IF IsOpenOffice THEN
  924. BEGIN
  925. END {IF};
  926. result := NOT (VarIsEmpty(m_vDocument) OR VarIsNull(m_vDocument));
  927. END {THojaCalc.GetDocLoaded};
  928. { ********************* }
  929. { ** Managing sheets ** }
  930. { ********************* }
  931. FUNCTION THojaCalc.GetCountSheets: integer;
  932. VAR
  933. vActiveSheet, vOoSheets: variant;
  934. AttrPtr: Pointer;
  935. BEGIN
  936. result := 0;
  937. IF DocLoaded THEN
  938. BEGIN
  939. IF IsExcel THEN
  940. TRY
  941. TRY
  942. IF VarIsEmpty(m_vDocument) OR VarIsNull(m_vDocument)
  943. THEN
  944. vActiveSheet := Unassigned
  945. ELSE
  946. vActiveSheet := m_vDocument.ActiveSheet;
  947. IF VarIsEmpty(vActiveSheet) OR VarIsNull(vActiveSheet)
  948. THEN
  949. result := 0
  950. ELSE
  951. result := m_vDocument.Sheets.count;
  952. EXCEPT
  953. result := 0;
  954. END {TRY};
  955. FINALLY
  956. END {TRY};
  957. IF IsOpenOffice THEN
  958. TRY
  959. TRY
  960. vOoSheets := m_vDocument.getSheets;
  961. AttrPtr := TVarData(vOoSheets).VDispatch;
  962. IF NOT assigned(AttrPtr) THEN
  963. vOoSheets := Unassigned;
  964. IF VarIsEmpty(vOoSheets) OR VarIsNull(vOoSheets)
  965. THEN
  966. result := 0
  967. ELSE
  968. result := vOoSheets.GetCount;
  969. EXCEPT
  970. result := 0;
  971. END {TRY};
  972. FINALLY
  973. END {TRY};
  974. END {IF};
  975. END {THojaCalc.GetCountSheets};
  976. FUNCTION THojaCalc.ActivateSheetByIndex (nIndex: integer): boolean;
  977. { Index is 1 based in Excel, but OpenOffice uses it 0-based }
  978. { Here we asume 1-based so OO needs to activate (nIndex-1) }
  979. BEGIN
  980. result := false;
  981. IF DocLoaded THEN
  982. BEGIN //
  983. //Exists this sheet number?
  984. IF (nIndex < 1) THEN
  985. RAISE Exception.Create('Can not activate sheet #' + IntToStr(nIndex));
  986. WHILE (nIndex > CountSheets) DO
  987. BEGIN
  988. ActivateSheetByIndex(CountSheets);
  989. AddNewSheet('New sheet ' + IntToStr(CountSheets + 1));
  990. sleep(100); //Needs time to do it!
  991. END {WHILE}; //
  992. //Activate it now...
  993. IF IsExcel THEN
  994. BEGIN
  995. m_vDocument.Sheets[nIndex].activate;
  996. m_vActiveSheet := m_vDocument.ActiveSheet;
  997. result := true;
  998. END {IF};
  999. IF IsOpenOffice THEN
  1000. BEGIN
  1001. m_vActiveSheet := m_vDocument.getSheets.getByIndex(nIndex - 1);
  1002. IF m_bVisible THEN
  1003. m_vDocument.getCurrentController.setactivesheet(m_vActiveSheet);
  1004. result := true;
  1005. END {IF};
  1006. sleep(100); //Asyncronus, so better give it time to make the change
  1007. END {IF};
  1008. END {THojaCalc.ActivateSheetByIndex};
  1009. FUNCTION THojaCalc.ActivateSheetByName (strSheetName: string; bCaseSensitive: boolean): boolean;
  1010. { Find a sheet by its name... }
  1011. VAR
  1012. vOldActiveSheet: variant;
  1013. i: integer;
  1014. BEGIN
  1015. result := false;
  1016. IF DocLoaded THEN
  1017. BEGIN
  1018. IF bCaseSensitive
  1019. THEN
  1020. BEGIN //
  1021. //Find the EXACT name...
  1022. IF IsExcel THEN
  1023. BEGIN
  1024. m_vDocument.Sheets[strSheetName].Select;
  1025. m_vActiveSheet := m_vDocument.ActiveSheet;
  1026. result := true;
  1027. END {IF};
  1028. IF IsOpenOffice THEN
  1029. BEGIN
  1030. m_vActiveSheet := m_vDocument.getSheets.getByName(strSheetName);
  1031. IF m_bVisible THEN
  1032. m_vDocument.getCurrentController.setactivesheet(m_vActiveSheet);
  1033. result := true;
  1034. END {IF};
  1035. END {IF}
  1036. ELSE
  1037. BEGIN //
  1038. //Find the Sheet regardless of the case...
  1039. vOldActiveSheet := m_vActiveSheet;
  1040. FOR i := 1 TO GetCountSheets DO
  1041. BEGIN
  1042. ActivateSheetByIndex(i);
  1043. IF UpperCase(ActiveSheetName) = UpperCase(strSheetName) THEN
  1044. BEGIN
  1045. result := true;
  1046. Exit;
  1047. END {IF};
  1048. END {FOR}; //
  1049. //IF NOT found, let the old active sheet active...
  1050. m_vActiveSheet := vOldActiveSheet;
  1051. END {ELSE};
  1052. END {IF};
  1053. END {THojaCalc.ActivateSheetByName};
  1054. FUNCTION THojaCalc.GetActiveSheetName: string;
  1055. { Name of the active sheet? }
  1056. BEGIN
  1057. IF DocLoaded THEN
  1058. BEGIN
  1059. IF IsExcel THEN
  1060. result := m_vActiveSheet.Name;
  1061. IF IsOpenOffice THEN
  1062. result := m_vActiveSheet.GetName;
  1063. END {IF};
  1064. END {THojaCalc.GetActiveSheetName};
  1065. PROCEDURE THojaCalc.SetActiveSheetName (strNewName: string);
  1066. BEGIN
  1067. IF DocLoaded THEN
  1068. BEGIN //
  1069. //Clean name first...
  1070. strNewName := ValidateSheetName(strNewName);
  1071. IF IsExcel THEN
  1072. m_vPrograma.ActiveSheet.Name := strNewName;
  1073. IF IsOpenOffice THEN
  1074. BEGIN
  1075. m_vActiveSheet.setName(strNewName); //
  1076. //This code always changes the name of "visible" sheet, not active one!
  1077. //ooParams := VarArrayCreate([0, 0], varVariant);
  1078. //ooParams[0] := ooCreateValue('Name', strNewName);
  1079. //ooDispatch('.uno:RenameTable', ooParams);
  1080. END {IF};
  1081. END {IF};
  1082. END {THojaCalc.SetActiveSheetName};
  1083. FUNCTION THojaCalc.IsActiveSheetProtected: boolean;
  1084. { Check for sheet protection (password)... }
  1085. BEGIN
  1086. result := false;
  1087. IF DocLoaded THEN
  1088. BEGIN
  1089. IF IsExcel THEN
  1090. result := m_vActiveSheet.ProtectContents;
  1091. IF IsOpenOffice THEN
  1092. result := m_vActiveSheet.IsProtected;
  1093. END {IF};
  1094. END {THojaCalc.IsActiveSheetProtected};
  1095. FUNCTION THojaCalc.PrintActiveSheet: boolean;
  1096. { WARNING: This function is NOT dual, only works for Excel docs! }
  1097. { Send active sheet to default printer (as seen in preview window)... }
  1098. BEGIN
  1099. result := false;
  1100. IF DocLoaded THEN
  1101. BEGIN
  1102. IF IsExcel THEN
  1103. BEGIN
  1104. m_vActiveSheet.PrintOut;
  1105. result := true;
  1106. END {IF};
  1107. IF IsOpenOffice THEN
  1108. BEGIN
  1109. RAISE Exception.Create('Function "PrintActiveSheet" still not working in OpenOffice!');//
  1110. //ActiveSheet.Print;
  1111. result := false;
  1112. END {IF};
  1113. END {IF};
  1114. END {THojaCalc.PrintActiveSheet};
  1115. FUNCTION THojaCalc.PrintSheetsUntil (strLastSheetName: string): boolean;
  1116. { WARNING: This function is NOT dual, only works for Excel docs! }
  1117. { Select and print sheets from 1 upto -excluded- the one with that name. }
  1118. { It is interesting for understanding how to pass an array of objects to excel. }
  1119. VAR
  1120. i, last: integer;
  1121. vHojas: variant;
  1122. BEGIN
  1123. result := false;
  1124. IF DocLoaded
  1125. THEN
  1126. BEGIN
  1127. IF IsExcel THEN
  1128. BEGIN //
  1129. //Macro from Excel:
  1130. // Sheets(Array("Hoja1", "Hoja2")).Select
  1131. // ActiveWindow.SelectedSheets.PrintOut Copies:=1, Collate:=True
  1132. //
  1133. //Which sheet number correspond to the one previous to "LastSheetName"?
  1134. Last := 0;
  1135. FOR i := 2 TO CountSheets DO
  1136. BEGIN
  1137. ActivateSheetByIndex(i);
  1138. IF UpperCase(ActiveSheetName) = UpperCase(strLastSheetName) THEN
  1139. BEGIN
  1140. Last := i - 1;
  1141. break;
  1142. END {IF};
  1143. END {FOR}; //
  1144. //Not found?
  1145. IF Last = 0 THEN
  1146. exit; //
  1147. //Create an array of variants -windows standard type- this big...
  1148. vHojas := VarArrayCreate([1, Last], varVariant); //
  1149. //Fill it with the Sheet names...
  1150. FOR i := 1 TO Last DO
  1151. BEGIN
  1152. ActivateSheetByIndex(i);
  1153. vHojas[i] := ActiveSheetName;
  1154. END {FOR}; //
  1155. //Print all this array of sheets...
  1156. m_vPrograma.Sheets[vHojas].Select;
  1157. m_vPrograma.ActiveWindow.SelectedSheets.PrintOut; //
  1158. //Done!
  1159. result := true;
  1160. END {IF};
  1161. IF IsOpenOffice THEN
  1162. BEGIN
  1163. RAISE Exception.Create('Function "PrintSheetsUntil" not working in OpenOffice!');
  1164. result := false;
  1165. END {IF};
  1166. END {IF};
  1167. END {THojaCalc.PrintSheetsUntil};
  1168. PROCEDURE THojaCalc.AddNewSheet (strNewName: string; bRemoveDummySheets: boolean = false);
  1169. { Add a new sheet, name it, and make it the active sheet... }
  1170. VAR
  1171. vOoSheets: variant;
  1172. BEGIN
  1173. strNewName := ValidateSheetName(strNewName);
  1174. IF NOT DocLoaded THEN
  1175. NewDoc(true);
  1176. IF DocLoaded THEN
  1177. BEGIN
  1178. IF IsExcel THEN
  1179. BEGIN
  1180. m_vDocument.WorkSheets.Add(null, m_vDocument.ActiveSheet, 1);
  1181. m_vDocument.ActiveSheet.Name := strNewName;
  1182. IF bRemoveDummySheets AND m_bFirstAddedSheet THEN
  1183. RemoveAllSheetsExcept(strNewName, true); //
  1184. //Active sheet has move to this new one, so I need to update the VAR
  1185. m_vActiveSheet := m_vDocument.ActiveSheet;
  1186. m_bFirstAddedSheet := false;
  1187. END {IF};
  1188. IF IsOpenOffice THEN
  1189. BEGIN
  1190. vOoSheets := m_vDocument.getSheets;
  1191. vOoSheets.insertNewByName(strNewName, 1);
  1192. IF bRemoveDummySheets AND m_bFirstAddedSheet THEN
  1193. RemoveAllSheetsExcept(strNewName, true); //
  1194. //Redefine active sheet to this new one
  1195. m_vActiveSheet := vOoSheets.getByName(strNewName);
  1196. IF m_bVisible THEN
  1197. m_vDocument.getCurrentController.setactivesheet(m_vActiveSheet);
  1198. m_bFirstAddedSheet := false;
  1199. END {IF};
  1200. END {IF};
  1201. END {THojaCalc.AddNewSheet};
  1202. PROCEDURE THojaCalc.RemoveSheetByName (strOldName: string);
  1203. { Remove an existing sheet by its name }
  1204. VAR
  1205. vOoSheets: variant;
  1206. BEGIN
  1207. IF DocLoaded THEN
  1208. BEGIN
  1209. IF IsExcel THEN
  1210. BEGIN
  1211. m_vDocument.WorkSheets[strOldName].Delete;
  1212. //Active sheet might have moved, so I need to update the VAR
  1213. m_vActiveSheet := m_vDocument.ActiveSheet;
  1214. END {IF};
  1215. IF IsOpenOffice THEN
  1216. BEGIN
  1217. vOoSheets := m_vDocument.getSheets;
  1218. vOoSheets.removeByName(strOldName); //
  1219. //Redefine active sheet to the current one
  1220. m_vActiveSheet := m_vDocument.getCurrentController.getActiveSheet;
  1221. END {IF};
  1222. END {IF};
  1223. END {THojaCalc.RemoveSheetByName};
  1224. PROCEDURE THojaCalc.RemoveSheetByIndex (nIndex: integer);
  1225. { Remove an existing sheet by its index }
  1226. VAR
  1227. vOoSheets, vOoSheet: variant;
  1228. strOldName: string;
  1229. BEGIN
  1230. IF DocLoaded THEN
  1231. BEGIN
  1232. IF (nIndex < 1) THEN
  1233. RAISE Exception.Create('Can not remove sheet #' + IntToStr(nIndex));
  1234. IF IsExcel THEN
  1235. BEGIN
  1236. m_vDocument.Sheets[nIndex].Delete;
  1237. //Active sheet might have moved, so I need to update the VAR
  1238. m_vActiveSheet := m_vDocument.ActiveSheet;
  1239. END {IF};
  1240. IF IsOpenOffice THEN
  1241. BEGIN
  1242. vOoSheets := m_vDocument.getSheets;
  1243. vOoSheet := vOoSheets.get…

Large files files are truncated, but you can click here to view the full file