/*
** Command & Conquer Renegade(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 .
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : LevelEdit *
* *
* $Archive:: /Commando/Code/Tools/LevelEdit/excel.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 1/17/02 1:43p $*
* *
* $Revision:: 4 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "stdafx.h"
///#include
#include "excel.h"
#include
#include
#include
#include
#include
#include "excel8.h"
#include "utils.h"
typedef enum {
xlAll = -4104,
xlAutomatic = -4105,
xlBoth = 1,
xlCenter = -4108,
xlChecker = 9,
xlCircle = 8,
xlCorner = 2,
xlCrissCross = 16,
xlCross = 4,
xlDiamond = 2,
xlDistributed = -4117,
xlDoubleAccounting = 5,
xlFixedValue = 1,
xlFormats = -4122,
xlGray16 = 17,
xlGray8 = 18,
xlGrid = 15,
xlHigh = -4127,
xlInside = 2,
xlJustify = -4130,
xlLightDown = 13,
xlLightHorizontal = 11,
xlLightUp = 14,
xlLightVertical = 12,
xlLow = -4134,
xlManual = -4135,
xlMinusValues = 3,
xlModule = -4141,
xlNextToAxis = 4,
xlNone = -4142,
xlNotes = -4144,
xlOff = -4146,
xlOn = 1,
xlPercent = 2,
xlPlus = 9,
xlPlusValues = 2,
xlSemiGray75 = 10,
xlShowLabel = 4,
xlShowLabelAndPercent = 5,
xlShowPercent = 3,
xlShowValue = 2,
xlSimple = -4154,
xlSingle = 2,
xlSingleAccounting = 4,
xlSolid = 1,
xlSquare = 1,
xlStar = 5,
xlStError = 4,
xlToolbarButton = 2,
xlTriangle = 3,
xlGray25 = -4124,
xlGray50 = -4125,
xlGray75 = -4126,
xlBottom = -4107,
xlLeft = -4131,
xlRight = -4152,
xlTop = -4160,
xl3DBar = -4099,
xl3DSurface = -4103,
xlBar = 2,
xlColumn = 3,
xlCombination = -4111,
xlCustom = -4114,
xlDefaultAutoFormat = -1,
xlMaximum = 2,
xlMinimum = 4,
xlOpaque = 3,
xlTransparent = 2,
xlBidi = -5000,
xlLatin = -5001,
xlContext = -5002,
xlLTR = -5003,
xlRTL = -5004,
xlVisualCursor = 2,
xlLogicalCursor = 1,
xlSystem = 1,
xlPartial = 3,
xlHindiNumerals = 3,
xlBidiCalendar = 3,
xlGregorian = 2,
xlComplete = 4,
xlScale = 3,
xlClosed = 3,
xlColor1 = 7,
xlColor2 = 8,
xlColor3 = 9,
xlConstants = 2,
xlContents = 2,
xlBelow = 1,
xlCascade = 7,
xlCenterAcrossSelection = 7,
xlChart4 = 2,
xlChartSeries = 17,
xlChartShort = 6,
xlChartTitles = 18,
xlClassic1 = 1,
xlClassic2 = 2,
xlClassic3 = 3,
xl3DEffects1 = 13,
xl3DEffects2 = 14,
xlAbove = 0,
xlAccounting1 = 4,
xlAccounting2 = 5,
xlAccounting3 = 6,
xlAccounting4 = 17,
xlAdd = 2,
xlDebugCodePane = 13,
xlDesktop = 9,
xlDirect = 1,
xlDivide = 5,
xlDoubleClosed = 5,
xlDoubleOpen = 4,
xlDoubleQuote = 1,
xlEntireChart = 20,
xlExcelMenus = 1,
xlExtended = 3,
xlFill = 5,
xlFirst = 0,
xlFloating = 5,
xlFormula = 5,
xlGeneral = 1,
xlGridline = 22,
xlIcons = 1,
xlImmediatePane = 12,
xlInteger = 2,
xlLast = 1,
xlLastCell = 11,
xlList1 = 10,
xlList2 = 11,
xlList3 = 12,
xlLocalFormat1 = 15,
xlLocalFormat2 = 16,
xlLong = 3,
xlLotusHelp = 2,
xlMacrosheetCell = 7,
xlMixed = 2,
xlMultiply = 4,
xlNarrow = 1,
xlNoDocuments = 3,
xlOpen = 2,
xlOutside = 3,
xlReference = 4,
xlSemiautomatic = 2,
xlShort = 1,
xlSingleQuote = 2,
xlStrict = 2,
xlSubtract = 3,
xlTextBox = 16,
xlTiled = 1,
xlTitleBar = 8,
xlToolbar = 1,
xlVisible = 12,
xlWatchPane = 11,
xlWide = 3,
xlWorkbookTab = 6,
xlWorksheet4 = 1,
xlWorksheetCell = 3,
xlWorksheetShort = 5,
xlAllExceptBorders = 6,
xlLeftToRight = 2,
xlTopToBottom = 1,
xlVeryHidden = 2,
xlDrawingObject = 14
} Constants;
typedef enum {
xlHairline = 1,
xlMedium = -4138,
xlThick = 4,
xlThin = 2
} XlBorderWeight;
typedef enum {
xlContinuous = 1,
xlDash = -4115,
xlDashDot = 4,
xlDashDotDot = 5,
xlDot = -4118,
xlDouble = -4119,
xlSlantDashDot = 13,
xlLineStyleNone = -4142
} XlLineStyle;
typedef enum {
xlInsideHorizontal = 12,
xlInsideVertical = 11,
xlDiagonalDown = 5,
xlDiagonalUp = 6,
xlEdgeBottom = 9,
xlEdgeLeft = 7,
xlEdgeRight = 10,
xlEdgeTop = 8
} XlBordersIndex;
static const int xlWorkbookNormal = -4143;
static const int xlNoChange = 1;
static const int xlLocalSessionChanges = 2;
static const int xlWBATWorksheet = -4167;
static VARIANT no, yes, dummy, dummy0, nullstring, empty;
static VARIANT continuous, automatic, medium, thin, none;
static VARIANT yellow, solid;
/////////////////////////////////////////////////////////////////////////
// Static member initialization
/////////////////////////////////////////////////////////////////////////
_Application * ExcelClass::Application = NULL;
Workbooks * ExcelClass::WorkbooksObj = NULL;
_Worksheet * ExcelClass::WorksheetObj = NULL;
_Workbook * ExcelClass::WorkbookObj = NULL;
Range * ExcelClass::RangeObj = NULL;
StringClass ExcelClass::CurrPath;
/////////////////////////////////////////////////////////////////////////
//
// Initialize
//
/////////////////////////////////////////////////////////////////////////
bool
ExcelClass::Initialize (void)
{
//
// Don't reinitialize
//
if (Application != NULL) {
return true;
}
bool retval = false;
//
// Allocate the application object
//
Application = new _Application;
//
// Attempt to start excel
//
if (Application->CreateDispatch ("Excel.Application")) {
//
// Get the workbook interface
//
LPDISPATCH dispatch = Application->GetWorkbooks ();
if (dispatch != NULL) {
retval = true;
//
// Create the neccessary interfaces
//
WorkbooksObj = new Workbooks (dispatch);
WorksheetObj = new _Worksheet;
RangeObj = new Range;
//
// Dunno
//
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 retval;
}
/////////////////////////////////////////////////////////////////////////
//
// Shutdown
//
/////////////////////////////////////////////////////////////////////////
void
ExcelClass::Shutdown (void)
{
Close_Workbook ();
//
// Free our interfaces
//
SAFE_DELETE (RangeObj);
SAFE_DELETE (WorksheetObj);
if (WorkbooksObj != NULL) {
WorkbooksObj->Close ();
SAFE_DELETE (WorksheetObj);
}
if (Application != NULL) {
Application->Quit ();
Application->ReleaseDispatch ();
SAFE_DELETE (Application);
}
//
// Dunno
//
VariantClear (&nullstring);
return ;
}
/////////////////////////////////////////////////////////////////////////
//
// New_Workbook
//
/////////////////////////////////////////////////////////////////////////
void
ExcelClass::New_Workbook (const char *template_filename)
{
if (template_filename == NULL) {
return ;
}
//
// Configure a variant with the filename we wish to add
//
WideStringClass wide_filename;
wide_filename.Convert_From (template_filename);
VARIANT temp;
V_VT (&temp) = VT_BSTR;
V_BSTR (&temp) = ::SysAllocString (wide_filename);
//
// Create the new workbook
//
LPDISPATCH dispatch = WorkbooksObj->Add (temp);
if (dispatch != NULL) {
//
// Create a new wrapper object for this workbook
//
WorkbookObj = new _Workbook (dispatch);
Select_Active_Sheet ();
}
//
// Free the variant's data
//
::VariantClear (&temp);
return ;
}
/////////////////////////////////////////////////////////////////////////
//
// Open_Workbookk
//
/////////////////////////////////////////////////////////////////////////
void
ExcelClass::Open_Workbook (const char *filename)
{
//
// Attempt to open this workbook
//
LPDISPATCH dispatch = WorkbooksObj->Open (filename, dummy0, yes, dummy, nullstring,
nullstring, yes, dummy, dummy, no, no, dummy, no);
if (dispatch != NULL) {
//
// Wrap the dispatch pointer in a friendlier object
//
WorkbookObj = new _Workbook (dispatch);
Select_Active_Sheet ();
}
return ;
}
/////////////////////////////////////////////////////////////////////////
//
// Save_Workbook
//
/////////////////////////////////////////////////////////////////////////
void
ExcelClass::Save_Workbook (const char *filename)
{
if (WorkbookObj == NULL) {
return ;
}
VARIANT name, fileformat, rc;
WideStringClass wide_filename;
wide_filename.Convert_From (filename);
V_VT (&name) = VT_BSTR;
V_BSTR (&name) = SysAllocString (wide_filename);
V_VT (&fileformat) = VT_I4;
V_I4 (&fileformat) = xlWorkbookNormal;
V_VT (&rc) = VT_I4;
V_I4 (&rc) = xlLocalSessionChanges;
WorkbookObj->SaveAs ( name, fileformat, nullstring, nullstring, no, no,
xlNoChange, rc, no, empty, empty );
VariantClear (&name);
/*if (WorkbookObj != NULL) {
WorkbookObj->Save ();
}*/
/*dispatch;
VARIANT temp;
V_VT ( &temp ) = VT_I4;
V_I4 ( &temp ) = xlWBATWorksheet;
if (CurrPath.Is_Empty () == false) {
//
// Check to see if the file still exists
//
if (::GetFileAttributes (CurrPath) != 0xFFFFFFFF) {
WideStringClass wide_filename;
wide_filename.Convert_From (CurrPath);
//
// Fill in the path of the file
//
V_VT (&temp) = VT_BSTR;
V_BSTR (&temp) = ::SysAllocString (wide_filename);
}
}
}
//
// Save the workbook and refresh our workbook object
//
LPDISPATCH dispatch = WorkbooksObj->Add (temp);
if (dispatch != NULL) {
WorkbookObj = new _Workbook (dispatch);
}
Select_Active_Sheet ();
VariantClear (&temp);*/
return ;
}
/////////////////////////////////////////////////////////////////////////
//
// Close_Workbook
//
/////////////////////////////////////////////////////////////////////////
void
ExcelClass::Close_Workbook (void)
{
//
// Simply close and delete the workbook
//
if (WorkbookObj != NULL) {
WorkbookObj->SetSaved (TRUE);
WorkbookObj->Close (no, nullstring, no);
SAFE_DELETE (WorkbookObj);
}
return ;
}
/////////////////////////////////////////////////////////////////////////
//
// Get_String
//
/////////////////////////////////////////////////////////////////////////
bool
ExcelClass::Get_String (int row, int col, WideStringClass &string)
{
bool retval = false;
//
// Get the cell's contents
//
VARIANT variant_value;
if (Get_Cell (row, col, variant_value)) {
//
// Is this a string?
//
if (V_VT (&variant_value) == VT_BSTR) {
string = V_BSTR (&variant_value);
retval = true;
} else if (V_VT (&variant_value) == VT_R4) {
int value = (int)variant_value.fltVal;
string.Format (L"%d", value);
retval = true;
} else if (V_VT (&variant_value) == VT_R8) {
int value = (int)variant_value.dblVal;
string.Format (L"%d", value);
retval = true;
} else if ( V_VT (&variant_value) == VT_I2 || V_VT (&variant_value) == VT_I4 ||
V_VT (&variant_value) == VT_UI2 || V_VT (&variant_value) == VT_UI4)
{
string.Format (L"%d", variant_value.iVal);
retval = true;
}
//
// Free the variant data
//
::VariantClear (&variant_value);
}
return retval;
}
/////////////////////////////////////////////////////////////////////////
//
// Set_String
//
/////////////////////////////////////////////////////////////////////////
bool
ExcelClass::Set_String (int row, int col, const WideStringClass &value)
{
//
// Configure a variant with the string data we want to set
//
VARIANT variant_value;
V_VT (&variant_value) = VT_BSTR;
V_BSTR (&variant_value) = ::SysAllocString (value);
//
// Put the string into the cell
//
bool retval = Set_Cell (row, col, variant_value);
//
// Free the variant data
//
::VariantClear (&variant_value);
return retval;
}
/////////////////////////////////////////////////////////////////////////
//
// Get_Int
//
/////////////////////////////////////////////////////////////////////////
bool
ExcelClass::Get_Int (int row, int col, int &value)
{
bool retval = false;
//
// Get the cell's contents
//
VARIANT variant_value;
if (Get_Cell (row, col, variant_value)) {
//
// Is this an integer?
//
if (V_VT (&variant_value) == VT_I4) {
value = V_I4(&variant_value);
retval = true;
}
//
// Free the variant data
//
::VariantClear (&variant_value);
}
return retval;
}
/////////////////////////////////////////////////////////////////////////
//
// Set_Int
//
/////////////////////////////////////////////////////////////////////////
bool
ExcelClass::Set_Int (int row, int col, int value)
{
//
// Configure a variant with the integer data we want to set
//
VARIANT variant_value;
V_VT (&variant_value) = VT_I4;
V_I4 (&variant_value) = value;
//
// Put the integer into the cell
//
bool retval = Set_Cell (row, col, variant_value);
//
// Free the variant data
//
::VariantClear (&variant_value);
return retval;
}
/////////////////////////////////////////////////////////////////////////
//
// Select_Active_Sheet
//
/////////////////////////////////////////////////////////////////////////
void
ExcelClass::Select_Active_Sheet (void)
{
LPDISPATCH dispatch = Application->GetActiveSheet ();
//
// If possible, attach the new worksheet
//
if (dispatch != NULL) {
WorksheetObj->ReleaseDispatch ();
WorksheetObj->AttachDispatch (dispatch);
}
return ;
}
/////////////////////////////////////////////////////////////////////////
//
// Get_Cell
//
/////////////////////////////////////////////////////////////////////////
bool
ExcelClass::Get_Cell (int row, int col, VARIANT &result)
{
if (WorksheetObj == NULL) {
return false;
}
bool retval = false;
//
// Generate the name of the cell we'll be using
//
WideStringClass cell_name;
cell_name.Format (L"%c%d", 'A'+col , row + 1);
//
// Configure a variant object for use as a cell ID
//
VARIANT cell;
V_VT (&cell) = VT_BSTR;
V_BSTR (&cell) = ::SysAllocString (cell_name);
//
// Get the data
//
LPDISPATCH dispatch = WorksheetObj->GetRange (cell, cell);
if (dispatch != NULL) {
//
// Retrieve the data from the range object
//
RangeObj->AttachDispatch (dispatch);
result = RangeObj->GetValue ();
RangeObj->ReleaseDispatch ();
retval = true;
}
//
// Free the variant data
//
::VariantClear (&cell);
return retval;
}
/////////////////////////////////////////////////////////////////////////
//
// Set_Cell
//
/////////////////////////////////////////////////////////////////////////
bool
ExcelClass::Set_Cell (int row, int col, const VARIANT &data)
{
if (WorksheetObj == NULL) {
return false;
}
bool retval = false;
//
// Generate the name of the cell we'll be using
//
WideStringClass cell_name;
cell_name.Format (L"%c%d", 'A'+col, row + 1);
//
// Configure a variant object for use as a cell ID
//
VARIANT cell;
V_VT (&cell) = VT_BSTR;
V_BSTR (&cell) = ::SysAllocString (cell_name);
//
// Get the cell range
//
LPDISPATCH dispatch = WorksheetObj->GetRange (cell, cell);
if (dispatch != NULL) {
//
// Shove our new data into this range
//
RangeObj->AttachDispatch (dispatch);
RangeObj->SetValue (data);
RangeObj->ReleaseDispatch ();
retval = true;
}
//
// Free the variant data
//
::VariantClear (&cell);
return retval;
}