674 lines
11 KiB
C++
674 lines
11 KiB
C++
![]() |
/*
|
||
|
** Command & Conquer Generals Zero Hour(tm)
|
||
|
** Copyright 2025 Electronic Arts Inc.
|
||
|
**
|
||
|
** This program is free software: you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation, either version 3 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** This program is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
//
|
||
|
// XLStuff.cpp
|
||
|
//
|
||
|
//
|
||
|
#include "stdAfx.h"
|
||
|
#include "Babylon.h"
|
||
|
#include "resource.h"
|
||
|
#include <stdio.h>
|
||
|
#include "xlstuff.h"
|
||
|
#include <assert.h>
|
||
|
#include <comdef.h>
|
||
|
|
||
|
static const int xlWorkbookNormal = -4143;
|
||
|
static const int xlNoChange = 1;
|
||
|
static const int xlLocalSessionChanges = 2;
|
||
|
static const int xlWBATWorksheet = -4167;
|
||
|
static _Workbook *workbook = NULL;
|
||
|
static _Application *xl = NULL;
|
||
|
static Workbooks *wbs = NULL;
|
||
|
static Range *range = NULL;
|
||
|
static _Worksheet *ws = NULL;
|
||
|
static OLECHAR buffer[100*1024];
|
||
|
|
||
|
static VARIANT no, yes, dummy, dummy0, nullstring, empty;
|
||
|
static VARIANT continuous, automatic, medium, thin, none;
|
||
|
static VARIANT yellow, solid;
|
||
|
|
||
|
static VARIANT GetCell ( int row, int column )
|
||
|
{
|
||
|
VARIANT cell;
|
||
|
VARIANT result;
|
||
|
LPDISPATCH dispatch;
|
||
|
OLECHAR cellname[20];
|
||
|
|
||
|
V_VT ( &cell ) = VT_EMPTY;
|
||
|
|
||
|
assert ( column > 0 );
|
||
|
swprintf ( cellname, L"%c%d", 'A'+column -1 , row );
|
||
|
V_VT ( &cell ) = VT_BSTR;
|
||
|
V_BSTR ( &cell ) = SysAllocString (cellname);
|
||
|
|
||
|
V_VT ( &result ) = VT_BOOL;
|
||
|
V_BOOL ( &result ) = FALSE;
|
||
|
|
||
|
if ( !ws )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
if ( ! (dispatch = ws->GetRange (cell, cell )))
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
|
||
|
range->AttachDispatch ( dispatch );
|
||
|
result = range->GetValue ();
|
||
|
range->ReleaseDispatch ( );
|
||
|
|
||
|
error:
|
||
|
|
||
|
VariantClear ( &cell );
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
int PutCell ( int row, int column, OLECHAR *string, int val )
|
||
|
{
|
||
|
VARIANT cell;
|
||
|
VARIANT newValue;
|
||
|
int ok = FALSE;
|
||
|
LPDISPATCH dispatch;
|
||
|
OLECHAR cellname[20];
|
||
|
|
||
|
|
||
|
V_VT ( &newValue ) = VT_EMPTY;
|
||
|
V_VT ( &cell ) = VT_EMPTY;
|
||
|
|
||
|
assert ( column > 0 );
|
||
|
swprintf ( cellname, L"%c%d", 'A'+column-1, row );
|
||
|
V_VT ( &cell ) = VT_BSTR;
|
||
|
V_BSTR ( &cell ) = SysAllocString (cellname);
|
||
|
|
||
|
if ( !ws )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
if ( ! (dispatch = ws->GetRange (cell, cell )))
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
range->AttachDispatch ( dispatch );
|
||
|
|
||
|
if ( string )
|
||
|
{
|
||
|
V_VT ( &newValue ) = VT_BSTR;
|
||
|
|
||
|
if ( string[0] == '\'')
|
||
|
{
|
||
|
buffer[0] = '\\';
|
||
|
wcscpy ( &buffer[1], string );
|
||
|
V_BSTR ( &newValue ) = SysAllocString ( buffer );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
V_BSTR ( &newValue ) = SysAllocString ( string );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
V_VT ( &newValue ) = VT_I4;
|
||
|
V_I4 ( &newValue ) = val;
|
||
|
}
|
||
|
|
||
|
range->SetValue ( newValue );
|
||
|
range->ReleaseDispatch ( );
|
||
|
ok = TRUE;
|
||
|
|
||
|
error:
|
||
|
|
||
|
|
||
|
VariantClear ( &cell );
|
||
|
VariantClear ( &newValue );
|
||
|
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
int PutSeparator ( int row )
|
||
|
{
|
||
|
// Rows(row).Select
|
||
|
// Selection.Borders(xlDiagonalDown).LineStyle = xlNone
|
||
|
// Selection.Borders(xlDiagonalUp).LineStyle = xlNone
|
||
|
// Selection.Borders(xlEdgeLeft).LineStyle = xlNone
|
||
|
// Selection.Borders(xlEdgeTop).LineStyle = xlNone
|
||
|
// With Selection.Borders(xlEdgeBottom)
|
||
|
// .LineStyle = xlContinuous
|
||
|
// .Weight = xlMedium
|
||
|
// .ColorIndex = xlAutomatic
|
||
|
// End With
|
||
|
// With Selection.Borders(xlEdgeRight)
|
||
|
// .LineStyle = xlContinuous
|
||
|
// .Weight = xlThin
|
||
|
// .ColorIndex = xlAutomatic
|
||
|
// End With
|
||
|
int ok = FALSE;
|
||
|
Border *border = NULL;
|
||
|
Borders *borders = NULL;
|
||
|
LPDISPATCH dispatch;
|
||
|
OLECHAR cellname1[20];
|
||
|
OLECHAR cellname2[20];
|
||
|
VARIANT cell1,cell2;
|
||
|
|
||
|
if ( !ws )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
assert ( row > 0 );
|
||
|
swprintf ( cellname1, L"A%d", row );
|
||
|
swprintf ( cellname2, L"%c%d", 'A'+CELL_LAST-1-1, row );
|
||
|
V_VT ( &cell1 ) = VT_BSTR;
|
||
|
V_BSTR ( &cell1 ) = SysAllocString (cellname1);
|
||
|
|
||
|
V_VT ( &cell2 ) = VT_BSTR;
|
||
|
V_BSTR ( &cell2 ) = SysAllocString (cellname2);
|
||
|
|
||
|
|
||
|
if ( ! (dispatch = ws->GetRange (cell1, cell2 )))
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
range->AttachDispatch ( dispatch );
|
||
|
|
||
|
dispatch = range->GetBorders ();
|
||
|
|
||
|
|
||
|
borders = new Borders ( dispatch );
|
||
|
|
||
|
if ( !borders )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
dispatch = borders->GetItem ( xlEdgeBottom );
|
||
|
|
||
|
border = new Border ( dispatch );
|
||
|
|
||
|
if ( !border )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
border->SetLineStyle ( continuous );
|
||
|
border->SetColorIndex ( automatic );
|
||
|
border->SetWeight ( thin );
|
||
|
|
||
|
ok = TRUE;
|
||
|
|
||
|
error:
|
||
|
|
||
|
range->ReleaseDispatch ( );
|
||
|
|
||
|
if ( borders )
|
||
|
{
|
||
|
delete borders ;
|
||
|
}
|
||
|
|
||
|
if ( border )
|
||
|
{
|
||
|
delete border ;
|
||
|
}
|
||
|
|
||
|
VariantClear ( &cell1 );
|
||
|
VariantClear ( &cell2 );
|
||
|
|
||
|
return ok;
|
||
|
}
|
||
|
|
||
|
|
||
|
int PutSection ( int row, OLECHAR *title )
|
||
|
{
|
||
|
|
||
|
int ok = FALSE;
|
||
|
Range *range = NULL;
|
||
|
Border *border = NULL;
|
||
|
Borders *borders = NULL;
|
||
|
Interior *interior = NULL;
|
||
|
LPDISPATCH dispatch;
|
||
|
OLECHAR cellname1[20];
|
||
|
OLECHAR cellname2[20];
|
||
|
VARIANT cell1,cell2;
|
||
|
_Worksheet *ws = NULL;
|
||
|
|
||
|
if ( !ws )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
assert ( row > 0 );
|
||
|
swprintf ( cellname1, L"A%d", row );
|
||
|
swprintf ( cellname2, L"%c%d", 'A'+CELL_LAST-1-1, row );
|
||
|
V_VT ( &cell1 ) = VT_BSTR;
|
||
|
V_BSTR ( &cell1 ) = SysAllocString (cellname1);
|
||
|
|
||
|
V_VT ( &cell2 ) = VT_BSTR;
|
||
|
V_BSTR ( &cell2 ) = SysAllocString (cellname2);
|
||
|
|
||
|
|
||
|
if ( ! (dispatch = ws->GetRange (cell1, cell2 )))
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
range->AttachDispatch ( dispatch );
|
||
|
|
||
|
dispatch = range->GetBorders ();
|
||
|
|
||
|
|
||
|
borders = new Borders ( dispatch );
|
||
|
|
||
|
if ( !borders )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
dispatch = borders->GetItem ( xlEdgeBottom );
|
||
|
|
||
|
border = new Border ( dispatch );
|
||
|
|
||
|
if ( !border )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
border->SetLineStyle ( continuous );
|
||
|
border->SetColorIndex ( automatic );
|
||
|
border->SetWeight ( thin );
|
||
|
|
||
|
delete border;
|
||
|
border = NULL;
|
||
|
|
||
|
dispatch = borders->GetItem ( xlEdgeTop );
|
||
|
|
||
|
border = new Border ( dispatch );
|
||
|
|
||
|
if ( !border )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
border->SetLineStyle ( continuous );
|
||
|
border->SetColorIndex ( automatic );
|
||
|
border->SetWeight ( medium );
|
||
|
|
||
|
delete border;
|
||
|
border = NULL;
|
||
|
|
||
|
dispatch = borders->GetItem ( xlEdgeRight );
|
||
|
|
||
|
border = new Border ( dispatch );
|
||
|
|
||
|
if ( !border )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
border->SetLineStyle ( none );
|
||
|
|
||
|
delete border;
|
||
|
border = NULL;
|
||
|
|
||
|
dispatch = borders->GetItem ( xlEdgeLeft );
|
||
|
|
||
|
border = new Border ( dispatch );
|
||
|
|
||
|
if ( !border )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
border->SetLineStyle ( none );
|
||
|
|
||
|
dispatch = range->GetInterior ( );
|
||
|
|
||
|
interior = new Interior ( dispatch );
|
||
|
|
||
|
if ( !interior )
|
||
|
{
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
interior->SetColorIndex ( yellow );
|
||
|
interior->SetPattern ( solid );
|
||
|
|
||
|
PutCell ( row, 1, L"Section", 0 );
|
||
|
PutCell ( row, 2, title, 0 );
|
||
|
|
||
|
ok = TRUE;
|
||
|
|
||
|
error:
|
||
|
|
||
|
range->ReleaseDispatch ( );
|
||
|
|
||
|
if ( borders )
|
||
|
{
|
||
|
delete borders ;
|
||
|
}
|
||
|
|
||
|
if ( border )
|
||
|
{
|
||
|
delete border ;
|
||
|
}
|
||
|
|
||
|
VariantClear ( &cell1 );
|
||
|
VariantClear ( &cell2 );
|
||
|
|
||
|
return ok;
|
||
|
|
||
|
}
|
||
|
|
||
|
int OpenExcel ( void )
|
||
|
{
|
||
|
LPDISPATCH dispatch;
|
||
|
|
||
|
if ( xl )
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
#if 0
|
||
|
while ( ExcelRunning ())
|
||
|
{
|
||
|
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 )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
xl = new _Application();
|
||
|
|
||
|
if ( !xl )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( !xl->CreateDispatch ("Excel.Application"))
|
||
|
{
|
||
|
goto error_access;
|
||
|
}
|
||
|
|
||
|
dispatch = xl->GetWorkbooks ( );
|
||
|
|
||
|
if ( dispatch )
|
||
|
{
|
||
|
wbs = new Workbooks( dispatch );
|
||
|
}
|
||
|
|
||
|
if ( !wbs )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( ! (ws = new _Worksheet ()))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( ! (range = new Range ()))
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
V_VT ( &no ) = VT_BOOL;
|
||
|
V_VT ( &yes ) = VT_BOOL;
|
||
|
V_VT ( &dummy ) = VT_I4;
|
||
|
V_VT ( &dummy0 ) = VT_I4;
|
||
|
V_VT ( &nullstring ) = VT_BSTR ;
|
||
|
V_VT ( &empty ) = VT_EMPTY;
|
||
|
V_VT ( &continuous ) = VT_I4;
|
||
|
V_VT ( &automatic ) = VT_I4;
|
||
|
V_VT ( &medium ) = VT_I4;
|
||
|
V_VT ( &thin ) = VT_I4;
|
||
|
V_VT ( &none ) = VT_I4;
|
||
|
V_VT ( &solid ) = VT_I4;
|
||
|
V_VT ( &yellow ) = VT_I4;
|
||
|
|
||
|
V_BOOL ( &no ) = FALSE;
|
||
|
V_BOOL ( &yes ) = TRUE;
|
||
|
V_I4 ( &dummy ) = 1;
|
||
|
V_I4 ( &dummy0 ) = 0;
|
||
|
V_BSTR ( &nullstring ) = SysAllocString ( OLESTR ("") );
|
||
|
|
||
|
V_I4 ( &continuous ) = xlContinuous;
|
||
|
V_I4 ( &automatic ) = xlAutomatic;
|
||
|
V_I4 ( &medium ) = xlMedium;
|
||
|
V_I4 ( &thin ) = xlThin;
|
||
|
V_I4 ( &none ) = xlThin;
|
||
|
V_I4 ( &solid ) = xlSolid;
|
||
|
V_I4 ( &yellow ) = 6;
|
||
|
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
error_access:
|
||
|
AfxMessageBox ("Could not access Excel!\n\nMake sure Excel is installed on this system.");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CloseExcel ( void )
|
||
|
{
|
||
|
CloseWorkBook ();
|
||
|
|
||
|
if ( range )
|
||
|
{
|
||
|
delete range;
|
||
|
range = NULL;
|
||
|
}
|
||
|
|
||
|
if ( ws )
|
||
|
{
|
||
|
delete ws;
|
||
|
ws = NULL;
|
||
|
}
|
||
|
|
||
|
if ( wbs )
|
||
|
{
|
||
|
wbs->Close();
|
||
|
delete wbs;
|
||
|
wbs = NULL;
|
||
|
}
|
||
|
|
||
|
if ( xl )
|
||
|
{
|
||
|
xl->Quit();
|
||
|
xl->ReleaseDispatch ();
|
||
|
delete xl;
|
||
|
xl = NULL;
|
||
|
}
|
||
|
|
||
|
VariantClear ( &nullstring );
|
||
|
|
||
|
}
|
||
|
|
||
|
int OpenWorkBook ( const char *filename )
|
||
|
{
|
||
|
LPDISPATCH dispatch;
|
||
|
|
||
|
dispatch = wbs->Open ((LPCTSTR) filename, dummy0, yes, dummy, nullstring, nullstring, yes, dummy, dummy, no, no, dummy, no );
|
||
|
|
||
|
if ( dispatch )
|
||
|
{
|
||
|
workbook = new _Workbook ( dispatch );
|
||
|
}
|
||
|
|
||
|
if ( !workbook )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
SelectActiveSheet ( );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
int NewWorkBook ( const char *path )
|
||
|
{
|
||
|
LPDISPATCH dispatch;
|
||
|
VARIANT temp;
|
||
|
char tfile[200];
|
||
|
char *p;
|
||
|
WIN32_FIND_DATA finfo;
|
||
|
HANDLE handle;
|
||
|
|
||
|
V_VT ( &temp ) = VT_I4;
|
||
|
V_I4 ( &temp ) = xlWBATWorksheet;
|
||
|
|
||
|
if ( path )
|
||
|
{
|
||
|
strcpy ( tfile, path );
|
||
|
if ( (p = strchr ( tfile, '.' )))
|
||
|
{
|
||
|
*p = 0;
|
||
|
}
|
||
|
|
||
|
strcpy ( p, ".xlt" );
|
||
|
|
||
|
if ( (handle = FindFirstFile ( tfile, &finfo)) != INVALID_HANDLE_VALUE )
|
||
|
{
|
||
|
if ( !(finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
|
||
|
{
|
||
|
swprintf ( buffer, L"%S", tfile );
|
||
|
V_VT ( &temp ) = VT_BSTR;
|
||
|
V_BSTR ( &temp ) = SysAllocString ( buffer );
|
||
|
}
|
||
|
|
||
|
FindClose ( handle );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dispatch = wbs->Add ( temp );
|
||
|
|
||
|
VariantClear ( &temp );
|
||
|
|
||
|
if ( dispatch )
|
||
|
{
|
||
|
workbook = new _Workbook ( dispatch );
|
||
|
}
|
||
|
|
||
|
if ( !workbook )
|
||
|
{
|
||
|
return FALSE;
|
||
|
}
|
||
|
SelectActiveSheet ( );
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
int SaveWorkBook ( const char *filename, int protect )
|
||
|
{
|
||
|
VARIANT name, fileformat, rc;
|
||
|
|
||
|
V_VT ( &name ) = VT_BSTR;
|
||
|
swprintf ( buffer, L"%S", filename );
|
||
|
V_BSTR ( &name ) = SysAllocString ( buffer );
|
||
|
|
||
|
V_VT ( &fileformat ) = VT_I4;
|
||
|
V_I4 ( &fileformat ) = xlWorkbookNormal;
|
||
|
|
||
|
|
||
|
V_VT ( &rc ) = VT_I4;
|
||
|
V_I4 ( &rc ) = xlLocalSessionChanges;
|
||
|
|
||
|
if ( protect )
|
||
|
{
|
||
|
VARIANT password;
|
||
|
V_VT ( &password ) = VT_BSTR;
|
||
|
V_BSTR ( &password ) = SysAllocString ( L"" );
|
||
|
|
||
|
ws->Protect ( password, yes, yes, yes, no );
|
||
|
VariantClear ( &password );
|
||
|
}
|
||
|
workbook->SaveAs ( name, fileformat, nullstring, nullstring, no, no,
|
||
|
xlNoChange, rc, no, empty, empty );
|
||
|
|
||
|
VariantClear ( &name );
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
}
|
||
|
|
||
|
void CloseWorkBook ( void )
|
||
|
{
|
||
|
if ( workbook )
|
||
|
{
|
||
|
workbook->SetSaved ( TRUE );
|
||
|
workbook->Close ( no, nullstring, no );
|
||
|
delete workbook;
|
||
|
workbook = NULL;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
void SelectActiveSheet ( void )
|
||
|
{
|
||
|
LPDISPATCH dispatch;
|
||
|
|
||
|
if ( ! (dispatch = xl->GetActiveSheet ()))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
ws->ReleaseDispatch ( );
|
||
|
ws->AttachDispatch ( dispatch );
|
||
|
}
|
||
|
|
||
|
int GetInt ( int row, int cell )
|
||
|
{
|
||
|
long value;
|
||
|
VARIANT var;
|
||
|
_variant_t v;
|
||
|
|
||
|
var = GetCell ( row, cell );
|
||
|
|
||
|
v.Attach ( var );
|
||
|
|
||
|
value = v;
|
||
|
|
||
|
return (int) value;
|
||
|
|
||
|
}
|
||
|
|
||
|
int GetString ( int row, int cell, OLECHAR *string )
|
||
|
{
|
||
|
VARIANT var;
|
||
|
|
||
|
string[0] =0;
|
||
|
var = GetCell ( row, cell );
|
||
|
|
||
|
if ( V_VT ( &var ) == VT_BSTR )
|
||
|
{
|
||
|
wcscpy ( string, V_BSTR ( &var ));
|
||
|
|
||
|
}
|
||
|
VariantClear ( &var );
|
||
|
|
||
|
return 1;
|
||
|
|
||
|
}
|
||
|
|