/* ** 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; }