XLStuff.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. //
  19. // XLStuff.cpp
  20. //
  21. //
  22. #include "stdAfx.h"
  23. #include "noxstring.h"
  24. #include "resource.h"
  25. #include <stdio.h>
  26. #include "xlstuff.h"
  27. #include <assert.h>
  28. #include <comdef.h>
  29. static const int xlWorkbookNormal = -4143;
  30. static const int xlNoChange = 1;
  31. static const int xlLocalSessionChanges = 2;
  32. static const int xlWBATWorksheet = -4167;
  33. static _Workbook *workbook = NULL;
  34. static _Application *xl = NULL;
  35. static Workbooks *wbs = NULL;
  36. static Range *range = NULL;
  37. static _Worksheet *ws = NULL;
  38. static OLECHAR buffer[100*1024];
  39. static VARIANT no, yes, dummy, dummy0, nullstring, empty;
  40. static VARIANT continuous, automatic, medium, thin, none;
  41. static VARIANT yellow, solid;
  42. static VARIANT GetCell ( int row, int column )
  43. {
  44. VARIANT cell;
  45. VARIANT result;
  46. LPDISPATCH dispatch;
  47. OLECHAR cellname[20];
  48. V_VT ( &cell ) = VT_EMPTY;
  49. assert ( column > 0 );
  50. swprintf ( cellname, L"%c%d", 'A'+column -1 , row );
  51. V_VT ( &cell ) = VT_BSTR;
  52. V_BSTR ( &cell ) = SysAllocString (cellname);
  53. V_VT ( &result ) = VT_BOOL;
  54. V_BOOL ( &result ) = FALSE;
  55. if ( !ws )
  56. {
  57. goto error;
  58. }
  59. if ( ! (dispatch = ws->GetRange (cell, cell )))
  60. {
  61. goto error;
  62. }
  63. range->AttachDispatch ( dispatch );
  64. result = range->GetValue ();
  65. range->ReleaseDispatch ( );
  66. error:
  67. VariantClear ( &cell );
  68. return result;
  69. }
  70. int PutCell ( int row, int column, OLECHAR *string, int val )
  71. {
  72. VARIANT cell;
  73. VARIANT newValue;
  74. int ok = FALSE;
  75. LPDISPATCH dispatch;
  76. OLECHAR cellname[20];
  77. V_VT ( &newValue ) = VT_EMPTY;
  78. V_VT ( &cell ) = VT_EMPTY;
  79. assert ( column > 0 );
  80. swprintf ( cellname, L"%c%d", 'A'+column-1, row );
  81. V_VT ( &cell ) = VT_BSTR;
  82. V_BSTR ( &cell ) = SysAllocString (cellname);
  83. if ( !ws )
  84. {
  85. goto error;
  86. }
  87. if ( ! (dispatch = ws->GetRange (cell, cell )))
  88. {
  89. goto error;
  90. }
  91. range->AttachDispatch ( dispatch );
  92. if ( string )
  93. {
  94. V_VT ( &newValue ) = VT_BSTR;
  95. if ( string[0] == '\'')
  96. {
  97. buffer[0] = '\\';
  98. wcscpy ( &buffer[1], string );
  99. V_BSTR ( &newValue ) = SysAllocString ( buffer );
  100. }
  101. else
  102. {
  103. V_BSTR ( &newValue ) = SysAllocString ( string );
  104. }
  105. }
  106. else
  107. {
  108. V_VT ( &newValue ) = VT_I4;
  109. V_I4 ( &newValue ) = val;
  110. }
  111. range->SetValue ( newValue );
  112. range->ReleaseDispatch ( );
  113. ok = TRUE;
  114. error:
  115. VariantClear ( &cell );
  116. VariantClear ( &newValue );
  117. return ok;
  118. }
  119. int PutSeparator ( int row )
  120. {
  121. // Rows(row).Select
  122. // Selection.Borders(xlDiagonalDown).LineStyle = xlNone
  123. // Selection.Borders(xlDiagonalUp).LineStyle = xlNone
  124. // Selection.Borders(xlEdgeLeft).LineStyle = xlNone
  125. // Selection.Borders(xlEdgeTop).LineStyle = xlNone
  126. // With Selection.Borders(xlEdgeBottom)
  127. // .LineStyle = xlContinuous
  128. // .Weight = xlMedium
  129. // .ColorIndex = xlAutomatic
  130. // End With
  131. // With Selection.Borders(xlEdgeRight)
  132. // .LineStyle = xlContinuous
  133. // .Weight = xlThin
  134. // .ColorIndex = xlAutomatic
  135. // End With
  136. int ok = FALSE;
  137. Border *border = NULL;
  138. Borders *borders = NULL;
  139. LPDISPATCH dispatch;
  140. OLECHAR cellname1[20];
  141. OLECHAR cellname2[20];
  142. VARIANT cell1,cell2;
  143. if ( !ws )
  144. {
  145. goto error;
  146. }
  147. assert ( row > 0 );
  148. swprintf ( cellname1, L"A%d", row );
  149. swprintf ( cellname2, L"%c%d", 'A'+CELL_LAST-1-1, row );
  150. V_VT ( &cell1 ) = VT_BSTR;
  151. V_BSTR ( &cell1 ) = SysAllocString (cellname1);
  152. V_VT ( &cell2 ) = VT_BSTR;
  153. V_BSTR ( &cell2 ) = SysAllocString (cellname2);
  154. if ( ! (dispatch = ws->GetRange (cell1, cell2 )))
  155. {
  156. goto error;
  157. }
  158. range->AttachDispatch ( dispatch );
  159. dispatch = range->GetBorders ();
  160. borders = new Borders ( dispatch );
  161. if ( !borders )
  162. {
  163. goto error;
  164. }
  165. dispatch = borders->GetItem ( xlEdgeBottom );
  166. border = new Border ( dispatch );
  167. if ( !border )
  168. {
  169. goto error;
  170. }
  171. border->SetLineStyle ( continuous );
  172. border->SetColorIndex ( automatic );
  173. border->SetWeight ( thin );
  174. ok = TRUE;
  175. error:
  176. range->ReleaseDispatch ( );
  177. if ( borders )
  178. {
  179. delete borders ;
  180. }
  181. if ( border )
  182. {
  183. delete border ;
  184. }
  185. VariantClear ( &cell1 );
  186. VariantClear ( &cell2 );
  187. return ok;
  188. }
  189. int PutSection ( int row, OLECHAR *title )
  190. {
  191. int ok = FALSE;
  192. Range *range = NULL;
  193. Border *border = NULL;
  194. Borders *borders = NULL;
  195. Interior *interior = NULL;
  196. LPDISPATCH dispatch;
  197. OLECHAR cellname1[20];
  198. OLECHAR cellname2[20];
  199. VARIANT cell1,cell2;
  200. _Worksheet *ws = NULL;
  201. if ( !ws )
  202. {
  203. goto error;
  204. }
  205. assert ( row > 0 );
  206. swprintf ( cellname1, L"A%d", row );
  207. swprintf ( cellname2, L"%c%d", 'A'+CELL_LAST-1-1, row );
  208. V_VT ( &cell1 ) = VT_BSTR;
  209. V_BSTR ( &cell1 ) = SysAllocString (cellname1);
  210. V_VT ( &cell2 ) = VT_BSTR;
  211. V_BSTR ( &cell2 ) = SysAllocString (cellname2);
  212. if ( ! (dispatch = ws->GetRange (cell1, cell2 )))
  213. {
  214. goto error;
  215. }
  216. range->AttachDispatch ( dispatch );
  217. dispatch = range->GetBorders ();
  218. borders = new Borders ( dispatch );
  219. if ( !borders )
  220. {
  221. goto error;
  222. }
  223. dispatch = borders->GetItem ( xlEdgeBottom );
  224. border = new Border ( dispatch );
  225. if ( !border )
  226. {
  227. goto error;
  228. }
  229. border->SetLineStyle ( continuous );
  230. border->SetColorIndex ( automatic );
  231. border->SetWeight ( thin );
  232. delete border;
  233. border = NULL;
  234. dispatch = borders->GetItem ( xlEdgeTop );
  235. border = new Border ( dispatch );
  236. if ( !border )
  237. {
  238. goto error;
  239. }
  240. border->SetLineStyle ( continuous );
  241. border->SetColorIndex ( automatic );
  242. border->SetWeight ( medium );
  243. delete border;
  244. border = NULL;
  245. dispatch = borders->GetItem ( xlEdgeRight );
  246. border = new Border ( dispatch );
  247. if ( !border )
  248. {
  249. goto error;
  250. }
  251. border->SetLineStyle ( none );
  252. delete border;
  253. border = NULL;
  254. dispatch = borders->GetItem ( xlEdgeLeft );
  255. border = new Border ( dispatch );
  256. if ( !border )
  257. {
  258. goto error;
  259. }
  260. border->SetLineStyle ( none );
  261. dispatch = range->GetInterior ( );
  262. interior = new Interior ( dispatch );
  263. if ( !interior )
  264. {
  265. goto error;
  266. }
  267. interior->SetColorIndex ( yellow );
  268. interior->SetPattern ( solid );
  269. PutCell ( row, 1, L"Section", 0 );
  270. PutCell ( row, 2, title, 0 );
  271. ok = TRUE;
  272. error:
  273. range->ReleaseDispatch ( );
  274. if ( borders )
  275. {
  276. delete borders ;
  277. }
  278. if ( border )
  279. {
  280. delete border ;
  281. }
  282. VariantClear ( &cell1 );
  283. VariantClear ( &cell2 );
  284. return ok;
  285. }
  286. int OpenExcel ( void )
  287. {
  288. LPDISPATCH dispatch;
  289. if ( xl )
  290. {
  291. return TRUE;
  292. }
  293. #if 0
  294. while ( ExcelRunning ())
  295. {
  296. if ( AfxMessageBox ( "Excel is running!\n\nClose or kill all instances of Excel and retry\n\nNOTE: Check task tray (CTRL-ALT-DELETE) for instances of Excel", MB_OKCANCEL ) == IDCANCEL )
  297. {
  298. return FALSE;
  299. }
  300. }
  301. #endif
  302. xl = new _Application();
  303. if ( !xl )
  304. {
  305. return FALSE;
  306. }
  307. if ( !xl->CreateDispatch ("Excel.Application"))
  308. {
  309. goto error_access;
  310. }
  311. dispatch = xl->GetWorkbooks ( );
  312. if ( dispatch )
  313. {
  314. wbs = new Workbooks( dispatch );
  315. }
  316. if ( !wbs )
  317. {
  318. return FALSE;
  319. }
  320. if ( ! (ws = new _Worksheet ()))
  321. {
  322. return FALSE;
  323. }
  324. if ( ! (range = new Range ()))
  325. {
  326. return FALSE;
  327. }
  328. V_VT ( &no ) = VT_BOOL;
  329. V_VT ( &yes ) = VT_BOOL;
  330. V_VT ( &dummy ) = VT_I4;
  331. V_VT ( &dummy0 ) = VT_I4;
  332. V_VT ( &nullstring ) = VT_BSTR ;
  333. V_VT ( &empty ) = VT_EMPTY;
  334. V_VT ( &continuous ) = VT_I4;
  335. V_VT ( &automatic ) = VT_I4;
  336. V_VT ( &medium ) = VT_I4;
  337. V_VT ( &thin ) = VT_I4;
  338. V_VT ( &none ) = VT_I4;
  339. V_VT ( &solid ) = VT_I4;
  340. V_VT ( &yellow ) = VT_I4;
  341. V_BOOL ( &no ) = FALSE;
  342. V_BOOL ( &yes ) = TRUE;
  343. V_I4 ( &dummy ) = 1;
  344. V_I4 ( &dummy0 ) = 0;
  345. V_BSTR ( &nullstring ) = SysAllocString ( OLESTR ("") );
  346. V_I4 ( &continuous ) = xlContinuous;
  347. V_I4 ( &automatic ) = xlAutomatic;
  348. V_I4 ( &medium ) = xlMedium;
  349. V_I4 ( &thin ) = xlThin;
  350. V_I4 ( &none ) = xlThin;
  351. V_I4 ( &solid ) = xlSolid;
  352. V_I4 ( &yellow ) = 6;
  353. return TRUE;
  354. error_access:
  355. AfxMessageBox ("Could not access Excel!\n\nMake sure Excel is installed on this system.");
  356. return FALSE;
  357. }
  358. void CloseExcel ( void )
  359. {
  360. CloseWorkBook ();
  361. if ( range )
  362. {
  363. delete range;
  364. range = NULL;
  365. }
  366. if ( ws )
  367. {
  368. delete ws;
  369. ws = NULL;
  370. }
  371. if ( wbs )
  372. {
  373. wbs->Close();
  374. delete wbs;
  375. wbs = NULL;
  376. }
  377. if ( xl )
  378. {
  379. xl->Quit();
  380. xl->ReleaseDispatch ();
  381. delete xl;
  382. xl = NULL;
  383. }
  384. VariantClear ( &nullstring );
  385. }
  386. int OpenWorkBook ( const char *filename )
  387. {
  388. LPDISPATCH dispatch;
  389. dispatch = wbs->Open ((LPCTSTR) filename, dummy0, yes, dummy, nullstring, nullstring, yes, dummy, dummy, no, no, dummy, no );
  390. if ( dispatch )
  391. {
  392. workbook = new _Workbook ( dispatch );
  393. }
  394. if ( !workbook )
  395. {
  396. return FALSE;
  397. }
  398. SelectActiveSheet ( );
  399. return TRUE;
  400. }
  401. int NewWorkBook ( const char *path )
  402. {
  403. LPDISPATCH dispatch;
  404. VARIANT temp;
  405. char tfile[200];
  406. char *p;
  407. WIN32_FIND_DATA finfo;
  408. HANDLE handle;
  409. V_VT ( &temp ) = VT_I4;
  410. V_I4 ( &temp ) = xlWBATWorksheet;
  411. if ( path )
  412. {
  413. strcpy ( tfile, path );
  414. if ( (p = strchr ( tfile, '.' )))
  415. {
  416. *p = 0;
  417. }
  418. strcpy ( p, ".xlt" );
  419. if ( (handle = FindFirstFile ( tfile, &finfo)) != INVALID_HANDLE_VALUE )
  420. {
  421. if ( !(finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  422. {
  423. swprintf ( buffer, L"%S", tfile );
  424. V_VT ( &temp ) = VT_BSTR;
  425. V_BSTR ( &temp ) = SysAllocString ( buffer );
  426. }
  427. FindClose ( handle );
  428. }
  429. }
  430. dispatch = wbs->Add ( temp );
  431. VariantClear ( &temp );
  432. if ( dispatch )
  433. {
  434. workbook = new _Workbook ( dispatch );
  435. }
  436. if ( !workbook )
  437. {
  438. return FALSE;
  439. }
  440. SelectActiveSheet ( );
  441. return TRUE;
  442. }
  443. int SaveWorkBook ( const char *filename, int protect )
  444. {
  445. VARIANT name, fileformat, rc;
  446. V_VT ( &name ) = VT_BSTR;
  447. swprintf ( buffer, L"%S", filename );
  448. V_BSTR ( &name ) = SysAllocString ( buffer );
  449. V_VT ( &fileformat ) = VT_I4;
  450. V_I4 ( &fileformat ) = xlWorkbookNormal;
  451. V_VT ( &rc ) = VT_I4;
  452. V_I4 ( &rc ) = xlLocalSessionChanges;
  453. if ( protect )
  454. {
  455. VARIANT password;
  456. V_VT ( &password ) = VT_BSTR;
  457. V_BSTR ( &password ) = SysAllocString ( L"" );
  458. ws->Protect ( password, yes, yes, yes, no );
  459. VariantClear ( &password );
  460. }
  461. workbook->SaveAs ( name, fileformat, nullstring, nullstring, no, no,
  462. xlNoChange, rc, no, empty, empty );
  463. VariantClear ( &name );
  464. return TRUE;
  465. }
  466. void CloseWorkBook ( void )
  467. {
  468. if ( workbook )
  469. {
  470. workbook->SetSaved ( TRUE );
  471. workbook->Close ( no, nullstring, no );
  472. delete workbook;
  473. workbook = NULL;
  474. }
  475. }
  476. void SelectActiveSheet ( void )
  477. {
  478. LPDISPATCH dispatch;
  479. if ( ! (dispatch = xl->GetActiveSheet ()))
  480. {
  481. return;
  482. }
  483. ws->ReleaseDispatch ( );
  484. ws->AttachDispatch ( dispatch );
  485. }
  486. int GetInt ( int row, int cell )
  487. {
  488. long value;
  489. VARIANT var;
  490. _variant_t v;
  491. var = GetCell ( row, cell );
  492. v.Attach ( var );
  493. value = v;
  494. return (int) value;
  495. }
  496. int GetString ( int row, int cell, OLECHAR *string )
  497. {
  498. VARIANT var;
  499. string[0] =0;
  500. var = GetCell ( row, cell );
  501. if ( V_VT ( &var ) == VT_BSTR )
  502. {
  503. wcscpy ( string, V_BSTR ( &var ));
  504. }
  505. VariantClear ( &var );
  506. return 1;
  507. }