CSpreadSheet类学习,用于操作excel表格。

废话不多说,先上代码。

[cpp]  view plain  copy
  1. // Class to read and write to Excel and text delimited spreadsheet  
  2. //  
  3. // Created by Yap Chun Wei  
  4. // December 2001  
  5. //   
  6. // Version 1.1  
  7. // Updates: Fix bug in ReadRow() which prevent reading of single column spreadsheet  
  8. // Modified by jingzhou xu  
  9. #ifndef CSPREADSHEET_H  
  10. #define CSPREADSHEET_H  
  11. #include <odbcinst.h>  
  12. #include <afxdb.h>  
  13.   
  14. class CSpreadSheet  
  15. {  
  16. public:  
  17.     CSpreadSheet(CString File, CString SheetOrSeparator, bool Backup = true); // Open spreadsheet for reading and writing  
  18.     ~CSpreadSheet(); // Perform some cleanup functions  
  19.     bool AddHeaders(CStringArray &FieldNames, bool replace = false); // Add header row to spreadsheet  
  20.     bool DeleteSheet(); // Clear text delimited file content  
  21.     bool DeleteSheet(CString SheetName); // Clear entire Excel spreadsheet content. The sheet itself is not deleted  
  22.     bool AddRow(CStringArray &RowValues, long row = 0, bool replace = false); // Insert or replace a row into spreadsheet. Default is add new row.   
  23.     bool AddCell(CString CellValue, CString column, long row = 0, bool Auto = true); // Replace or add a cell into Excel spreadsheet using header row or column alphabet. Default is add cell into new row. Set Auto to false if want to force column to be used as header name  
  24.     bool AddCell(CString CellValue, short column, long row = 0); // Replace or add a cell into spreadsheet using column number. Default is add cell into new row.   
  25.     bool ReplaceRows(CStringArray &NewRowValues, CStringArray &OldRowValues); // Search and replace rows in Excel spreadsheet  
  26.     bool ReadRow(CStringArray &RowValues, long row = 0); // Read a row from spreadsheet. Default is read the next row  
  27.     bool ReadColumn(CStringArray &ColumnValues, CString column, bool Auto = true); // Read a column from Excel spreadsheet using header row or column alphabet. Set Auto to false if want to force column to be used as header name  
  28.     bool ReadColumn(CStringArray &ColumnValues, short column); // Read a column from spreadsheet using column number  
  29.     bool ReadCell (CString &CellValue, CString column, long row = 0, bool Auto = true); // Read a cell from Excel spreadsheet using header row or column alphabet. Default is read the next cell in next row. Set Auto to false if want to force column to be used as header name  
  30.     bool ReadCell (CString &CellValue, short column, long row = 0); // Read a cell from spreadsheet using column number. Default is read the next cell in next row.  
  31.     void BeginTransaction(); // Begin transaction  
  32.     bool Commit(); // Save changes to spreadsheet  
  33.     bool RollBack(); // Undo changes to spreadsheet  
  34.     bool Convert(CString SheetOrSeparator);  
  35.     inline void GetFieldNames (CStringArray &FieldNames) {FieldNames.RemoveAll(); FieldNames.Copy(m_aFieldNames);} // Get the header row from spreadsheet  
  36.     inline long GetTotalRows() {return m_dTotalRows;} // Get total number of rows in  spreadsheet  
  37.     inline short GetTotalColumns() {return m_dTotalColumns;} // Get total number of columns in  spreadsheet  
  38.     inline long GetCurrentRow() {return m_dCurrentRow;} // Get the currently selected row in  spreadsheet  
  39.     inline bool GetBackupStatus() {return m_bBackup;} // Get status of backup. True if backup is successful, False if spreadsheet is not backup  
  40.     inline bool GetTransactionStatus() {return m_bTransaction;} // Get status of Transaction. True if Transaction is started, False if Transaction is not started or has error in starting  
  41.     inline CString GetLastError() {return m_sLastError;} // Get last error message  
  42.   
  43. private:  
  44.     bool Open(); // Open a text delimited file for reading or writing  
  45.     void GetExcelDriver(); // Get the name of the Excel-ODBC driver  
  46.     short CalculateColumnNumber(CString column, bool Auto); // Convert Excel column in alphabet into column number  
  47.   
  48.     bool m_bAppend; // Internal flag to denote newly created spreadsheet or previously created spreadsheet  
  49.     bool m_bBackup; // Internal flag to denote status of Backup  
  50.     bool m_bExcel; // Internal flag to denote whether file is Excel spreadsheet or text delimited spreadsheet  
  51.     bool m_bTransaction; // Internal flag to denote status of Transaction  
  52.   
  53.     long m_dCurrentRow; // Index of current row, starting from 1  
  54.     long m_dTotalRows; // Total number of rows in spreadsheet  
  55.     short m_dTotalColumns; // Total number of columns in Excel spreadsheet. Largest number of columns in text delimited spreadsheet  
  56.   
  57.     CString m_sSql; // SQL statement to open Excel spreadsheet for reading  
  58.     CString m_sDsn; // DSN string to open Excel spreadsheet for reading and writing  
  59.     CString m_stempSql; // Temporary string for SQL statements or for use by functions  
  60.     CString m_stempString; // Temporary string for use by functions  
  61.     CString m_sSheetName; // Sheet name of Excel spreadsheet  
  62.     CString m_sExcelDriver; // Name of Excel Driver  
  63.     CString m_sFile; // Spreadsheet file name  
  64.     CString m_sSeparator; // Separator in text delimited spreadsheet  
  65.     CString m_sLastError; // Last error message  
  66.   
  67.     CStringArray m_atempArray; // Temporary array for use by functions  
  68.     CStringArray m_aFieldNames; // Header row in spreadsheet  
  69.     CStringArray m_aRows; // Content of all the rows in spreadsheet  
  70.   
  71.     CDatabase *m_Database; // Database variable for Excel spreadsheet  
  72.     CRecordset *m_rSheet; // Recordset for Excel spreadsheet  
  73. };  
  74.   
  75. #endif  
  76.   
  77.   
  78.   
  79.   
  80.   
  81.   
  82.   
  83.   
  84.   
  85.   
  86.   
  87. #include "CSpreadSheet.h"  
  88.   
  89. // Open spreadsheet for reading and writing  
  90. CSpreadSheet::CSpreadSheet(CString File, CString SheetOrSeparator, bool Backup) :  
  91.     m_Database(NULL), m_rSheet(NULL), m_sFile(File),  
  92.     m_dTotalRows(0), m_dTotalColumns(0), m_dCurrentRow(1),  
  93.     m_bAppend(false), m_bBackup(Backup), m_bTransaction(false)  
  94. {  
  95.     // Detect whether file is an Excel spreadsheet or a text delimited file  
  96.     m_stempString = m_sFile.Right(4);  
  97.     m_stempString.MakeLower();  
  98.     if (m_stempString == ".xls"// File is an Excel spreadsheet  
  99.     {  
  100.         m_bExcel = true;  
  101.         m_sSheetName = SheetOrSeparator;  
  102.         m_sSeparator = ",;.?";  
  103.     }  
  104.     else // File is a text delimited file  
  105.     {  
  106.         m_bExcel = false;  
  107.         m_sSeparator = SheetOrSeparator;  
  108.     }  
  109.   
  110.     if (m_bExcel) // If file is an Excel spreadsheet  
  111.     {  
  112.         m_Database = new CDatabase;  
  113.         GetExcelDriver();  
  114.         m_sDsn.Format("DRIVER={%s};DSN='';FIRSTROWHASNAMES=1;READONLY=FALSE;CREATE_DB=/"%s/";DBQ=%s", m_sExcelDriver, m_sFile, m_sFile);  
  115.   
  116.         if (Open())  
  117.         {  
  118.             if (m_bBackup)  
  119.             {  
  120.                 if ((m_bBackup) && (m_bAppend))  
  121.                 {  
  122.                     CString tempSheetName = m_sSheetName;  
  123.                     m_sSheetName = "CSpreadSheetBackup";  
  124.                     m_bAppend = false;  
  125.                     if (!Commit())  
  126.                     {  
  127.                         m_bBackup = false;  
  128.                     }  
  129.                     m_bAppend = true;  
  130.                     m_sSheetName = tempSheetName;  
  131.                     m_dCurrentRow = 1;  
  132.                 }  
  133.             }  
  134.         }  
  135.     }  
  136.     else // if file is a text delimited file  
  137.     {  
  138.         if (Open())  
  139.         {  
  140.             if ((m_bBackup) && (m_bAppend))  
  141.             {  
  142.                 m_stempString = m_sFile;  
  143.                 m_stempSql.Format("%s.bak", m_sFile);  
  144.                 m_sFile = m_stempSql;  
  145.                 if (!Commit())  
  146.                 {  
  147.                     m_bBackup = false;  
  148.                 }  
  149.                 m_sFile = m_stempString;  
  150.             }  
  151.         }  
  152.     }  
  153. }  
  154.   
  155. // Perform some cleanup functions  
  156. CSpreadSheet::~CSpreadSheet()  
  157. {  
  158.     if (m_Database != NULL)  
  159.     {  
  160.         m_Database->Close();  
  161.         delete m_Database;  
  162.     }  
  163. }  
  164.   
  165. // Add header row to spreadsheet  
  166. bool CSpreadSheet::AddHeaders(CStringArray &FieldNames, bool replace)  
  167. {  
  168.     if (m_bAppend) // Append to old Sheet  
  169.     {  
  170.         if (replace) // Replacing header row rather than adding new columns  
  171.         {  
  172.             if (!AddRow(FieldNames, 1, true))  
  173.             {  
  174.                 return false;  
  175.             }  
  176.             else  
  177.             {  
  178.                 return true;  
  179.             }  
  180.         }  
  181.   
  182.         if (ReadRow(m_atempArray, 1)) // Add new columns  
  183.         {  
  184.             if (m_bExcel)  
  185.             {  
  186.                 // Check for duplicate header row field  
  187.                 for (int i = 0; i < FieldNames.GetSize(); i++)  
  188.                 {  
  189.                     for (int j = 0; j < m_atempArray.GetSize(); j++)  
  190.                     {  
  191.                         if (FieldNames.GetAt(i) == m_atempArray.GetAt(j))  
  192.                         {  
  193.                             m_sLastError.Format("Duplicate header row field:%s/n", FieldNames.GetAt(i));  
  194.                             return false;  
  195.                         }  
  196.                     }  
  197.                 }     
  198.             }  
  199.   
  200.             m_atempArray.Append(FieldNames);  
  201.             if (!AddRow(m_atempArray, 1, true))  
  202.             {  
  203.                 m_sLastError = "Problems with adding headers/n";  
  204.                 return false;  
  205.             }  
  206.   
  207.             // Update largest number of columns if necessary  
  208.             if (m_atempArray.GetSize() > m_dTotalColumns)  
  209.             {  
  210.                 m_dTotalColumns = m_atempArray.GetSize();  
  211.             }  
  212.             return true;  
  213.         }  
  214.         return false;                 
  215.     }  
  216.     else // New Sheet  
  217.     {  
  218.         m_dTotalColumns = FieldNames.GetSize();  
  219.         if (!AddRow(FieldNames, 1, true))  
  220.         {  
  221.             return false;  
  222.         }  
  223.         else  
  224.         {  
  225.             m_dTotalRows = 1;  
  226.             return true;  
  227.         }  
  228.     }  
  229. }  
  230.   
  231. // Clear text delimited file content  
  232. bool CSpreadSheet::DeleteSheet()  
  233. {  
  234.     if (m_bExcel)  
  235.     {  
  236.         if (DeleteSheet(m_sSheetName))  
  237.         {  
  238.             return true;  
  239.         }  
  240.         else  
  241.         {  
  242.             m_sLastError = "Error deleting sheet/n";  
  243.             return false;  
  244.         }  
  245.     }  
  246.     else  
  247.     {  
  248.         m_aRows.RemoveAll();  
  249.         m_aFieldNames.RemoveAll();  
  250.         m_dTotalColumns = 0;  
  251.         m_dTotalRows = 0;  
  252.         if (!m_bTransaction)  
  253.         {  
  254.             Commit();             
  255.         }  
  256.         m_bAppend = false// Set flag to new sheet  
  257.         return true;          
  258.     }  
  259. }  
  260.   
  261. // Clear entire Excel spreadsheet content. The sheet itself is not deleted  
  262. bool CSpreadSheet::DeleteSheet(CString SheetName)  
  263. {  
  264.     if (m_bExcel) // If file is an Excel spreadsheet  
  265.     {  
  266.         // Delete sheet  
  267.         m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);  
  268.         SheetName = "[" + SheetName + "$A1:IV65536]";  
  269.         m_stempSql.Format ("DROP TABLE %s", SheetName);  
  270.         try  
  271.         {  
  272.             m_Database->ExecuteSQL(m_stempSql);  
  273.             m_Database->Close();  
  274.             m_aRows.RemoveAll();  
  275.             m_aFieldNames.RemoveAll();  
  276.             m_dTotalColumns = 0;  
  277.             m_dTotalRows = 0;  
  278.         }  
  279.         catch(CDBException *e)  
  280.         {  
  281.             m_sLastError = e->m_strError;  
  282.             m_Database->Close();  
  283.             return false;  
  284.         }  
  285.         return true;  
  286.     }  
  287.     else // if file is a text delimited file  
  288.     {  
  289.         return DeleteSheet();  
  290.     }  
  291. }  
  292.   
  293. // Insert or replace a row into spreadsheet.   
  294. // Default is add new row.  
  295. bool CSpreadSheet::AddRow(CStringArray &RowValues, long row, bool replace)  
  296. {  
  297.     long tempRow;  
  298.       
  299.     if (row == 1)  
  300.     {  
  301.         if (m_bExcel)   
  302.         {  
  303.             // Check for duplicate header row field for Excel spreadsheet  
  304.             for (int i = 0; i < RowValues.GetSize(); i++)  
  305.             {  
  306.                 for (int j = 0; j < RowValues.GetSize(); j++)  
  307.                 {  
  308.                     if ((i != j) && (RowValues.GetAt(i) == RowValues.GetAt(j)))  
  309.                     {  
  310.                         m_sLastError.Format("Duplicate header row field:%s/n", RowValues.GetAt(i));  
  311.                         return false;  
  312.                     }  
  313.                 }  
  314.             }  
  315.               
  316.             // Check for reduced header row columns  
  317.             if (RowValues.GetSize() < m_dTotalColumns)  
  318.             {  
  319.                 m_sLastError = "Number of columns in new header row cannot be less than the number of columns in previous header row";  
  320.                 return false;  
  321.             }  
  322.             m_dTotalColumns = RowValues.GetSize();  
  323.         }  
  324.   
  325.         // Update header row  
  326.         m_aFieldNames.RemoveAll();  
  327.         m_aFieldNames.Copy(RowValues);  
  328.     }  
  329.     else  
  330.     {  
  331.         if (m_bExcel)  
  332.         {  
  333.             if (m_dTotalColumns == 0)  
  334.             {  
  335.                 m_sLastError = "No header row. Add header row first/n";  
  336.                 return false;  
  337.             }  
  338.         }  
  339.     }  
  340.   
  341.     if (m_bExcel) // For Excel spreadsheet  
  342.     {  
  343.         if (RowValues.GetSize() > m_aFieldNames.GetSize())  
  344.         {  
  345.             m_sLastError = "Number of columns to be added cannot be greater than the number of fields/n";  
  346.             return false;  
  347.         }  
  348.     }  
  349.     else // For text delimited spreadsheet  
  350.     {  
  351.         // Update largest number of columns if necessary  
  352.         if (RowValues.GetSize() > m_dTotalColumns)  
  353.         {  
  354.             m_dTotalColumns = RowValues.GetSize();  
  355.         }  
  356.     }  
  357.   
  358.     // Convert row values  
  359.     m_stempString.Empty();  
  360.     for (int i = 0; i < RowValues.GetSize(); i++)  
  361.     {  
  362.         if (i != RowValues.GetSize()-1) // Not last column  
  363.         {  
  364.             m_stempSql.Format("/"%s/"%s", RowValues.GetAt(i), m_sSeparator);  
  365.             m_stempString += m_stempSql;  
  366.         }  
  367.         else // Last column  
  368.         {  
  369.             m_stempSql.Format("/"%s/"", RowValues.GetAt(i));  
  370.             m_stempString += m_stempSql;  
  371.         }  
  372.     }  
  373.       
  374.     if (row)  
  375.     {  
  376.         if (row <= m_dTotalRows) // Not adding new rows  
  377.         {  
  378.             if (replace) // Replacing row  
  379.             {  
  380.                 m_aRows.SetAt(row-1, m_stempString);  
  381.             }  
  382.             else // Inserting row  
  383.             {  
  384.                 m_aRows.InsertAt(row-1, m_stempString);  
  385.                 m_dTotalRows++;  
  386.             }  
  387.   
  388.             if (!m_bTransaction)  
  389.             {  
  390.                 Commit();  
  391.             }  
  392.             return true;  
  393.         }  
  394.         else // Adding new rows  
  395.         {  
  396.             // Insert null rows until specified row  
  397.             m_dCurrentRow = m_dTotalRows;  
  398.             m_stempSql.Empty();  
  399.             CString nullString;  
  400.             for (int i = 1; i <= m_dTotalColumns; i++)  
  401.             {  
  402.                 if (i != m_dTotalColumns)  
  403.                 {  
  404.                     if (m_bExcel)  
  405.                     {  
  406.                         nullString.Format("/" /"%s", m_sSeparator);  
  407.                     }  
  408.                     else  
  409.                     {  
  410.                         nullString.Format("/"/"%s", m_sSeparator);  
  411.                     }  
  412.                     m_stempSql += nullString;  
  413.                 }  
  414.                 else  
  415.                 {  
  416.                     if (m_bExcel)  
  417.                     {  
  418.                         m_stempSql += "/" /"";  
  419.                     }  
  420.                     else  
  421.                     {  
  422.                         m_stempSql += "/"/"";  
  423.                     }  
  424.                 }  
  425.             }  
  426.             for (int j = m_dTotalRows + 1; j < row; j++)  
  427.             {  
  428.                 m_dCurrentRow++;  
  429.                 m_aRows.Add(m_stempSql);  
  430.             }  
  431.         }  
  432.     }  
  433.     else  
  434.     {  
  435.         tempRow = m_dCurrentRow;  
  436.         m_dCurrentRow = m_dTotalRows;  
  437.     }  
  438.   
  439.     // Insert new row  
  440.     m_dCurrentRow++;  
  441.     m_aRows.Add(m_stempString);  
  442.       
  443.     if (row > m_dTotalRows)  
  444.     {  
  445.         m_dTotalRows = row;  
  446.     }  
  447.     else if (!row)  
  448.     {  
  449.         m_dTotalRows = m_dCurrentRow;  
  450.         m_dCurrentRow = tempRow;  
  451.     }  
  452.     if (!m_bTransaction)  
  453.     {  
  454.         Commit();  
  455.     }  
  456.     return true;  
  457. }  
  458.   
  459. // Replace or add a cell into Excel spreadsheet using header row or column alphabet.   
  460. // Default is add cell into new row.  
  461. // Set Auto to false if want to force column to be used as header name  
  462. bool CSpreadSheet::AddCell(CString CellValue, CString column, long row, bool Auto)  
  463. {  
  464.     short columnIndex = CalculateColumnNumber(column, Auto);  
  465.     if (columnIndex == 0)  
  466.     {  
  467.         return false;  
  468.     }  
  469.   
  470.     if (AddCell(CellValue, columnIndex, row))  
  471.     {  
  472.         return true;  
  473.     }  
  474.     return false;  
  475. }  
  476.   
  477. // Replace or add a cell into spreadsheet using column number  
  478. // Default is add cell into new row.  
  479. bool CSpreadSheet::AddCell(CString CellValue, short column, long row)  
  480. {  
  481.     if (column == 0)  
  482.     {  
  483.         m_sLastError = "Column cannot be zero/n";  
  484.         return false;  
  485.     }  
  486.   
  487.     long tempRow;  
  488.   
  489.     if (m_bExcel) // For Excel spreadsheet  
  490.     {  
  491.         if (column > m_aFieldNames.GetSize() + 1)  
  492.         {  
  493.             m_sLastError = "Cell column to be added cannot be greater than the number of fields/n";  
  494.             return false;  
  495.         }  
  496.     }  
  497.     else // For text delimited spreadsheet  
  498.     {  
  499.         // Update largest number of columns if necessary  
  500.         if (column > m_dTotalColumns)  
  501.         {  
  502.             m_dTotalColumns = column;  
  503.         }  
  504.     }  
  505.   
  506.     if (row)  
  507.     {  
  508.         if (row <= m_dTotalRows)  
  509.         {  
  510.             ReadRow(m_atempArray, row);  
  511.       
  512.             // Change desired row  
  513.             m_atempArray.SetAtGrow(column-1, CellValue);  
  514.   
  515.             if (row == 1)  
  516.             {  
  517.                 if (m_bExcel) // Check for duplicate header row field  
  518.                 {                                         
  519.                     for (int i = 0; i < m_atempArray.GetSize(); i++)  
  520.                     {  
  521.                         for (int j = 0; j < m_atempArray.GetSize(); j++)  
  522.                         {  
  523.                             if ((i != j) && (m_atempArray.GetAt(i) == m_atempArray.GetAt(j)))  
  524.                             {  
  525.                                 m_sLastError.Format("Duplicate header row field:%s/n", m_atempArray.GetAt(i));  
  526.                                 return false;  
  527.                             }  
  528.                         }  
  529.                     }  
  530.                 }  
  531.   
  532.                 // Update header row  
  533.                 m_aFieldNames.RemoveAll();  
  534.                 m_aFieldNames.Copy(m_atempArray);  
  535.             }     
  536.   
  537.             if (!AddRow(m_atempArray, row, true))  
  538.             {  
  539.                 return false;  
  540.             }  
  541.   
  542.             if (!m_bTransaction)  
  543.             {  
  544.                 Commit();  
  545.             }  
  546.             return true;  
  547.         }  
  548.         else  
  549.         {  
  550.             // Insert null rows until specified row  
  551.             m_dCurrentRow = m_dTotalRows;  
  552.             m_stempSql.Empty();  
  553.             CString nullString;  
  554.             for (int i = 1; i <= m_dTotalColumns; i++)  
  555.             {  
  556.                 if (i != m_dTotalColumns)  
  557.                 {  
  558.                     if (m_bExcel)  
  559.                     {  
  560.                         nullString.Format("/" /"%s", m_sSeparator);  
  561.                     }  
  562.                     else  
  563.                     {  
  564.                         nullString.Format("/"/"%s", m_sSeparator);  
  565.                     }  
  566.                     m_stempSql += nullString;  
  567.                 }  
  568.                 else  
  569.                 {  
  570.                     if (m_bExcel)  
  571.                     {  
  572.                         m_stempSql += "/" /"";  
  573.                     }  
  574.                     else  
  575.                     {  
  576.                         m_stempSql += "/"/"";  
  577.                     }  
  578.                 }  
  579.             }  
  580.             for (int j = m_dTotalRows + 1; j < row; j++)  
  581.             {  
  582.                 m_dCurrentRow++;  
  583.                 m_aRows.Add(m_stempSql);  
  584.             }  
  585.         }  
  586.     }  
  587.     else  
  588.     {  
  589.         tempRow = m_dCurrentRow;  
  590.         m_dCurrentRow = m_dTotalRows;  
  591.     }  
  592.   
  593.     // Insert cell  
  594.     m_dCurrentRow++;  
  595.     m_stempString.Empty();  
  596.     for (int j = 1; j <= m_dTotalColumns; j++)  
  597.     {  
  598.         if (j != m_dTotalColumns) // Not last column  
  599.         {  
  600.             if (j != column)  
  601.             {  
  602.                 if (m_bExcel)  
  603.                 {  
  604.                     m_stempSql.Format("/" /"%s", m_sSeparator);  
  605.                 }  
  606.                 else  
  607.                 {  
  608.                     m_stempSql.Format("/"/"%s", m_sSeparator);  
  609.                 }  
  610.                 m_stempString += m_stempSql;  
  611.             }  
  612.             else  
  613.             {  
  614.                 m_stempSql.Format("/"%s/"%s", CellValue, m_sSeparator);  
  615.                 m_stempString += m_stempSql;  
  616.             }  
  617.         }  
  618.         else // Last column  
  619.         {  
  620.             if (j != column)  
  621.             {  
  622.                 if (m_bExcel)  
  623.                 {  
  624.                     m_stempString += "/" /"";  
  625.                 }  
  626.                 else  
  627.                 {  
  628.                     m_stempString += "/"/"";  
  629.                 }  
  630.             }  
  631.             else  
  632.             {  
  633.                 m_stempSql.Format("/"%s/"", CellValue);  
  634.                 m_stempString += m_stempSql;  
  635.             }  
  636.         }  
  637.     }     
  638.   
  639.     m_aRows.Add(m_stempString);  
  640.       
  641.     if (row > m_dTotalRows)  
  642.     {  
  643.         m_dTotalRows = row;  
  644.     }  
  645.     else if (!row)  
  646.     {  
  647.         m_dTotalRows = m_dCurrentRow;  
  648.         m_dCurrentRow = tempRow;  
  649.     }  
  650.     if (!m_bTransaction)  
  651.     {  
  652.         Commit();  
  653.     }  
  654.     return true;  
  655. }  
  656.   
  657. // Search and replace rows in Excel spreadsheet  
  658. bool CSpreadSheet::ReplaceRows(CStringArray &NewRowValues, CStringArray &OldRowValues)  
  659. {  
  660.     if (m_bExcel) // If file is an Excel spreadsheet  
  661.     {  
  662.         m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);  
  663.         m_stempSql.Format("UPDATE [%s] SET ", m_sSheetName);  
  664.         for (int i = 0; i < NewRowValues.GetSize(); i++)  
  665.         {  
  666.             m_stempString.Format("[%s]='%s', ", m_aFieldNames.GetAt(i), NewRowValues.GetAt(i));  
  667.             m_stempSql = m_stempSql + m_stempString;  
  668.         }  
  669.         m_stempSql.Delete(m_stempSql.GetLength()-2, 2);  
  670.         m_stempSql = m_stempSql + " WHERE (";  
  671.         for (int j = 0; j < OldRowValues.GetSize()-1; j++)  
  672.         {  
  673.             m_stempString.Format("[%s]='%s' AND ", m_aFieldNames.GetAt(j), OldRowValues.GetAt(j));  
  674.             m_stempSql = m_stempSql + m_stempString;  
  675.         }  
  676.         m_stempSql.Delete(m_stempSql.GetLength()-4, 5);  
  677.         m_stempSql += ")";  
  678.   
  679.         try  
  680.         {  
  681.             m_Database->ExecuteSQL(m_stempSql);  
  682.             m_Database->Close();  
  683.             Open();  
  684.             return true;  
  685.         }  
  686.         catch(CDBException *e)  
  687.         {  
  688.             m_sLastError = e->m_strError;  
  689.             m_Database->Close();  
  690.             return false;  
  691.         }  
  692.     }  
  693.     else // if file is a text delimited file  
  694.     {  
  695.         m_sLastError = "Function not available for text delimited file/n";  
  696.         return false;  
  697.     }  
  698. }  
  699.   
  700. // Read a row from spreadsheet.   
  701. // Default is read the next row  
  702. bool CSpreadSheet::ReadRow(CStringArray &RowValues, long row)  
  703. {  
  704.     // Check if row entered is more than number of rows in sheet  
  705.     if (row <= m_aRows.GetSize())  
  706.     {  
  707.         if (row != 0)  
  708.         {  
  709.             m_dCurrentRow = row;  
  710.         }  
  711.         else if (m_dCurrentRow > m_aRows.GetSize())  
  712.         {  
  713.             return false;  
  714.         }  
  715.         // Read the desired row  
  716.         RowValues.RemoveAll();  
  717.         m_stempString = m_aRows.GetAt(m_dCurrentRow-1);  
  718.         m_dCurrentRow++;  
  719.   
  720.         // Search for separator to split row  
  721.         int separatorPosition;  
  722.         m_stempSql.Format("/"%s/"", m_sSeparator);  
  723.         separatorPosition = m_stempString.Find(m_stempSql); // If separator is "?"  
  724.         if (separatorPosition != -1)  
  725.         {  
  726.             // Save columns  
  727.             int nCount = 0;  
  728.             int stringStartingPosition = 0;  
  729.             while (separatorPosition != -1)  
  730.             {  
  731.                 nCount = separatorPosition - stringStartingPosition;  
  732.                 RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));  
  733.                 stringStartingPosition = separatorPosition + m_stempSql.GetLength();  
  734.                 separatorPosition = m_stempString.Find(m_stempSql, stringStartingPosition);  
  735.             }  
  736.             nCount = m_stempString.GetLength() - stringStartingPosition;  
  737.             RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));  
  738.   
  739.             // Remove quotes from first column  
  740.             m_stempString = RowValues.GetAt(0);  
  741.             m_stempString.Delete(0, 1);  
  742.             RowValues.SetAt(0, m_stempString);  
  743.               
  744.             // Remove quotes from last column  
  745.             m_stempString = RowValues.GetAt(RowValues.GetSize()-1);  
  746.             m_stempString.Delete(m_stempString.GetLength()-1, 1);  
  747.             RowValues.SetAt(RowValues.GetSize()-1, m_stempString);  
  748.   
  749.             return true;  
  750.         }  
  751.         else  
  752.         {  
  753.             // Save columns  
  754.             separatorPosition = m_stempString.Find(m_sSeparator); // if separator is ?  
  755.             if (separatorPosition != -1)  
  756.             {  
  757.                 int nCount = 0;  
  758.                 int stringStartingPosition = 0;  
  759.                 while (separatorPosition != -1)  
  760.                 {  
  761.                     nCount = separatorPosition - stringStartingPosition;  
  762.                     RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));  
  763.                     stringStartingPosition = separatorPosition + m_sSeparator.GetLength();  
  764.                     separatorPosition = m_stempString.Find(m_sSeparator, stringStartingPosition);  
  765.                 }  
  766.                 nCount = m_stempString.GetLength() - stringStartingPosition;  
  767.                 RowValues.Add(m_stempString.Mid(stringStartingPosition, nCount));  
  768.                 return true;  
  769.             }  
  770.             else    // Treat spreadsheet as having one column  
  771.             {  
  772.                 // Remove opening and ending quotes if any  
  773.                 int quoteBegPos = m_stempString.Find('/"');  
  774.                 int quoteEndPos = m_stempString.ReverseFind('/"');  
  775.                 if ((quoteBegPos == 0) && (quoteEndPos == m_stempString.GetLength()-1))  
  776.                 {  
  777.                     m_stempString.Delete(0, 1);  
  778.                     m_stempString.Delete(m_stempString.GetLength()-1, 1);  
  779.                 }  
  780.   
  781.                 RowValues.Add(m_stempString);  
  782.             }  
  783.         }  
  784.     }  
  785.     m_sLastError = "Desired row is greater than total number of rows in spreadsheet/n";  
  786.     return false;  
  787. }  
  788.   
  789. // Read a column from Excel spreadsheet using header row or column alphabet.   
  790. // Set Auto to false if want to force column to be used as header name  
  791. bool CSpreadSheet::ReadColumn(CStringArray &ColumnValues, CString column, bool Auto)  
  792. {  
  793.     short columnIndex = CalculateColumnNumber(column, Auto);  
  794.     if (columnIndex == 0)  
  795.     {  
  796.         return false;  
  797.     }  
  798.   
  799.     if (ReadColumn(ColumnValues, columnIndex))  
  800.     {  
  801.         return true;  
  802.     }  
  803.     return false;  
  804. }  
  805.   
  806. // Read a column from spreadsheet using column number  
  807. bool CSpreadSheet::ReadColumn(CStringArray &ColumnValues, short column)  
  808. {  
  809.     if (column == 0)  
  810.     {  
  811.         m_sLastError = "Column cannot be zero/n";  
  812.         return false;  
  813.     }  
  814.   
  815.     int tempRow = m_dCurrentRow;  
  816.     m_dCurrentRow = 1;  
  817.     ColumnValues.RemoveAll();  
  818.     for (int i = 1; i <= m_aRows.GetSize(); i++)  
  819.     {  
  820.         // Read each row  
  821.         if (ReadRow(m_atempArray, i))  
  822.         {  
  823.             // Get value of cell in desired column  
  824.             if (column <= m_atempArray.GetSize())  
  825.             {  
  826.                 ColumnValues.Add(m_atempArray.GetAt(column-1));  
  827.             }  
  828.             else  
  829.             {  
  830.                 ColumnValues.Add("");  
  831.             }  
  832.         }  
  833.         else  
  834.         {  
  835.             m_dCurrentRow = tempRow;  
  836.             m_sLastError = "Error reading row/n";  
  837.             return false;  
  838.         }  
  839.     }  
  840.     m_dCurrentRow = tempRow;  
  841.     return true;  
  842. }  
  843.   
  844. // Read a cell from Excel spreadsheet using header row or column alphabet.   
  845. // Default is read the next cell in next row.   
  846. // Set Auto to false if want to force column to be used as header name  
  847. bool CSpreadSheet::ReadCell (CString &CellValue, CString column, long row, bool Auto)  
  848. {  
  849.     short columnIndex = CalculateColumnNumber(column, Auto);  
  850.     if (columnIndex == 0)  
  851.     {  
  852.         return false;  
  853.     }  
  854.   
  855.     if (ReadCell(CellValue, columnIndex, row))  
  856.     {  
  857.         return true;  
  858.     }  
  859.     return false;  
  860. }  
  861.   
  862. // Read a cell from spreadsheet using column number.   
  863. // Default is read the next cell in next row.  
  864. bool CSpreadSheet::ReadCell (CString &CellValue, short column, long row)  
  865. {  
  866.     if (column == 0)  
  867.     {  
  868.         m_sLastError = "Column cannot be zero/n";  
  869.         return false;  
  870.     }  
  871.   
  872.     int tempRow = m_dCurrentRow;  
  873.     if (row)  
  874.     {  
  875.         m_dCurrentRow = row;  
  876.     }  
  877.     if (ReadRow(m_atempArray, m_dCurrentRow))  
  878.     {  
  879.         // Get value of cell in desired column  
  880.         if (column <= m_atempArray.GetSize())  
  881.         {  
  882.             CellValue = m_atempArray.GetAt(column-1);  
  883.         }  
  884.         else  
  885.         {  
  886.             CellValue.Empty();  
  887.             m_dCurrentRow = tempRow;  
  888.             return false;  
  889.         }  
  890.         m_dCurrentRow = tempRow;  
  891.         return true;  
  892.     }  
  893.     m_dCurrentRow = tempRow;  
  894.     m_sLastError = "Error reading row/n";  
  895.     return false;  
  896. }  
  897.   
  898. // Begin transaction  
  899. void CSpreadSheet::BeginTransaction()  
  900. {  
  901.     m_bTransaction = true;  
  902. }  
  903.   
  904. // Save changes to spreadsheet  
  905. bool CSpreadSheet::Commit()  
  906. {  
  907.     if (m_bExcel) // If file is an Excel spreadsheet  
  908.     {  
  909.         m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);  
  910.   
  911.         if (m_bAppend)  
  912.         {  
  913.             // Delete old sheet if it exists  
  914.             m_stempString= "[" + m_sSheetName + "$A1:IV65536]";  
  915.             m_stempSql.Format ("DROP TABLE %s", m_stempString);  
  916.             try  
  917.             {  
  918.                 m_Database->ExecuteSQL(m_stempSql);  
  919.             }  
  920.             catch(CDBException *e)  
  921.             {  
  922.                 m_sLastError = e->m_strError;  
  923.                 m_Database->Close();  
  924.                 return false;  
  925.             }  
  926.               
  927.             // Create new sheet  
  928.             m_stempSql.Format("CREATE TABLE [%s$A1:IV65536] (", m_sSheetName);  
  929.             for (int j = 0; j < m_aFieldNames.GetSize(); j++)  
  930.             {  
  931.                 m_stempSql = m_stempSql + "[" + m_aFieldNames.GetAt(j) +"]" + " char(255), ";  
  932.             }  
  933.             m_stempSql.Delete(m_stempSql.GetLength()-2, 2);  
  934.             m_stempSql += ")";  
  935.         }  
  936.         else  
  937.         {  
  938.             // Create new sheet  
  939.             m_stempSql.Format("CREATE TABLE [%s] (", m_sSheetName);  
  940.             for (int i = 0; i < m_aFieldNames.GetSize(); i++)  
  941.             {  
  942.                 m_stempSql = m_stempSql + "[" + m_aFieldNames.GetAt(i) +"]" + " char(255), ";  
  943.             }  
  944.             m_stempSql.Delete(m_stempSql.GetLength()-2, 2);  
  945.             m_stempSql += ")";  
  946.         }  
  947.   
  948.         try  
  949.         {  
  950.             m_Database->ExecuteSQL(m_stempSql);  
  951.             if (!m_bAppend)  
  952.             {  
  953.                 m_dTotalColumns = m_aFieldNames.GetSize();  
  954.                 m_bAppend = true;  
  955.             }  
  956.         }  
  957.         catch(CDBException *e)  
  958.         {  
  959.             m_sLastError = e->m_strError;  
  960.             m_Database->Close();  
  961.             return false;  
  962.         }  
  963.   
  964.         // Save changed data  
  965.         for (int k = 1; k < m_dTotalRows; k++)  
  966.         {  
  967.             ReadRow(m_atempArray, k+1);  
  968.   
  969.             // Create Insert SQL  
  970.             m_stempSql.Format("INSERT INTO [%s$A1:IV%d] (", m_sSheetName, k);  
  971.             for (int i = 0; i < m_atempArray.GetSize(); i++)  
  972.             {  
  973.                 m_stempString.Format("[%s], ", m_aFieldNames.GetAt(i));  
  974.                 m_stempSql = m_stempSql + m_stempString;  
  975.             }  
  976.             m_stempSql.Delete(m_stempSql.GetLength()-2, 2);  
  977.             m_stempSql += ") VALUES (";  
  978.             for (int j = 0; j < m_atempArray.GetSize(); j++)  
  979.             {  
  980.                 m_stempString.Format("'%s', ", m_atempArray.GetAt(j));  
  981.                 m_stempSql = m_stempSql + m_stempString;  
  982.             }  
  983.             m_stempSql.Delete(m_stempSql.GetLength()-2, 2);  
  984.             m_stempSql += ")";  
  985.   
  986.             // Add row  
  987.             try  
  988.             {  
  989.                 m_Database->ExecuteSQL(m_stempSql);  
  990.             }  
  991.             catch(CDBException *e)  
  992.             {  
  993.                 m_sLastError = e->m_strError;  
  994.                 m_Database->Close();  
  995.                 return false;  
  996.             }  
  997.         }  
  998.         m_Database->Close();  
  999.         m_bTransaction = false;  
  1000.         return true;  
  1001.     }  
  1002.     else // if file is a text delimited file  
  1003.     {  
  1004.         try  
  1005.         {  
  1006.             CFile *File = NULL;  
  1007.             File = new CFile(m_sFile, CFile::modeCreate | CFile::modeWrite  | CFile::shareDenyNone);  
  1008.             if (File != NULL)  
  1009.             {  
  1010.                 CArchive *Archive = NULL;  
  1011.                 Archive = new CArchive(File, CArchive::store);  
  1012.                 if (Archive != NULL)  
  1013.                 {  
  1014.                     for (int i = 0; i < m_aRows.GetSize(); i++)  
  1015.                     {  
  1016.                         Archive->WriteString(m_aRows.GetAt(i));  
  1017.                         Archive->WriteString("/r/n");  
  1018.                     }  
  1019.                     delete Archive;  
  1020.                     delete File;  
  1021.                     m_bTransaction = false;  
  1022.                     return true;  
  1023.                 }  
  1024.                 delete File;  
  1025.             }  
  1026.         }  
  1027.         catch(...)  
  1028.         {  
  1029.         }  
  1030.         m_sLastError = "Error writing file/n";  
  1031.         return false;  
  1032.     }  
  1033. }  
  1034.   
  1035. // Undo changes to spreadsheet  
  1036. bool CSpreadSheet::RollBack()  
  1037. {  
  1038.     if (Open())  
  1039.     {  
  1040.         m_bTransaction = false;  
  1041.         return true;  
  1042.     }  
  1043.     m_sLastError = "Error in returning to previous state/n";  
  1044.     return false;  
  1045. }  
  1046.   
  1047. bool CSpreadSheet::Convert(CString SheetOrSeparator)  
  1048. {  
  1049.     // Prepare file  
  1050.     m_stempString = m_sFile;  
  1051.     m_stempString.Delete(m_stempString.GetLength()-4, 4);  
  1052.     if (m_bExcel) // If file is an Excel spreadsheet  
  1053.     {  
  1054.         m_stempString += ".csv";  
  1055.         CSpreadSheet tempSheet(m_stempString, SheetOrSeparator, false);  
  1056.           
  1057.         // Stop convert if text delimited file exists  
  1058.         if (tempSheet.GetTotalColumns() != 0)  
  1059.         {  
  1060.             return false;  
  1061.         }  
  1062.   
  1063.         tempSheet.BeginTransaction();  
  1064.   
  1065.         for (int i = 1; i <= m_dTotalRows; i++)  
  1066.         {  
  1067.             if (!ReadRow(m_atempArray, i))  
  1068.             {  
  1069.                 return false;  
  1070.             }  
  1071.             if (!tempSheet.AddRow(m_atempArray, i))  
  1072.             {  
  1073.                 return false;  
  1074.             }  
  1075.         }  
  1076.         if (!tempSheet.Commit())  
  1077.         {  
  1078.             return false;  
  1079.         }  
  1080.         return true;  
  1081.     }  
  1082.     else // if file is a text delimited file  
  1083.     {  
  1084.         m_stempString += ".xls";  
  1085.         CSpreadSheet tempSheet(m_stempString, SheetOrSeparator, false);  
  1086.   
  1087.         // Stop convert if Excel file exists  
  1088.         if (tempSheet.GetTotalColumns() != 0)  
  1089.         {  
  1090.             return false;  
  1091.         }  
  1092.   
  1093.         GetFieldNames(m_atempArray);  
  1094.   
  1095.         // Check for duplicate header row field  
  1096.         bool duplicate = false;  
  1097.         for (int i = 0; i < m_atempArray.GetSize(); i++)  
  1098.         {  
  1099.             for (int j = 0; j < m_atempArray.GetSize(); j++)  
  1100.             {  
  1101.                 if ((i != j) && (m_atempArray.GetAt(i) == m_atempArray.GetAt(j)))  
  1102.                 {  
  1103.                     m_sLastError.Format("Duplicate header row field:%s/n", m_atempArray.GetAt(i));  
  1104.                     duplicate = true;  
  1105.                 }  
  1106.             }  
  1107.         }  
  1108.   
  1109.         if (duplicate) // Create dummy header row  
  1110.         {  
  1111.             m_atempArray.RemoveAll();  
  1112.             for (int k = 1; k <= m_dTotalColumns; k++)  
  1113.             {  
  1114.                 m_stempString.Format("%d", k);  
  1115.                 m_atempArray.Add(m_stempString);  
  1116.             }  
  1117.   
  1118.             if (!tempSheet.AddHeaders(m_atempArray))  
  1119.             {  
  1120.                 return false;  
  1121.             }  
  1122.   
  1123.             for (int l = 1; l <= m_dTotalRows; l++)  
  1124.             {  
  1125.                 if (!ReadRow(m_atempArray, l))  
  1126.                 {  
  1127.                     return false;  
  1128.                 }  
  1129.                 if (!tempSheet.AddRow(m_atempArray, l+1))  
  1130.                 {  
  1131.                     return false;  
  1132.                 }  
  1133.             }  
  1134.             return true;  
  1135.         }  
  1136.         else  
  1137.         {  
  1138.             if (!tempSheet.AddHeaders(m_atempArray))  
  1139.             {  
  1140.                 return false;  
  1141.             }  
  1142.   
  1143.             for (int l = 2; l <= m_dTotalRows; l++)  
  1144.             {  
  1145.                 if (!ReadRow(m_atempArray, l))  
  1146.                 {  
  1147.                     return false;  
  1148.                 }  
  1149.                 if (!tempSheet.AddRow(m_atempArray, l))  
  1150.                 {  
  1151.                     return false;  
  1152.                 }  
  1153.             }  
  1154.             return true;  
  1155.         }  
  1156.     }  
  1157. }  
  1158.   
  1159. // Open a text delimited file for reading or writing  
  1160. bool CSpreadSheet::Open()  
  1161. {  
  1162.     if (m_bExcel) // If file is an Excel spreadsheet  
  1163.     {  
  1164.         m_Database->OpenEx(m_sDsn, CDatabase::noOdbcDialog);  
  1165.   
  1166.         // Open Sheet  
  1167.         m_rSheet = new CRecordset( m_Database );  
  1168.         m_sSql.Format("SELECT * FROM [%s$A1:IV65536]", m_sSheetName);  
  1169.         try  
  1170.         {  
  1171.             m_rSheet->Open(CRecordset::forwardOnly, m_sSql, CRecordset::readOnly);  
  1172.         }  
  1173.         catch(...)  
  1174.         {  
  1175.             delete m_rSheet;  
  1176.             m_rSheet = NULL;  
  1177.             m_Database->Close();  
  1178.             return false;  
  1179.         }  
  1180.   
  1181.         // Get number of columns  
  1182.         m_dTotalColumns = m_rSheet->m_nResultCols;  
  1183.   
  1184.         if (m_dTotalColumns != 0)  
  1185.         {  
  1186.             m_aRows.RemoveAll();  
  1187.             m_stempString.Empty();  
  1188.             m_bAppend = true;  
  1189.             m_dTotalRows++; // Keep count of total number of rows  
  1190.               
  1191.             // Get field names i.e header row  
  1192.             for (int i = 0; i < m_dTotalColumns; i++)  
  1193.             {  
  1194.                 m_stempSql = m_rSheet->m_rgODBCFieldInfos[i].m_strName;  
  1195.                 m_aFieldNames.Add(m_stempSql);  
  1196.   
  1197.                 // Join up all the columns into a string  
  1198.                 if (i != m_dTotalColumns-1) // Not last column  
  1199.                 {  
  1200.                     m_stempString = m_stempString + "/"" + m_stempSql + "/"" + m_sSeparator;  
  1201.                 }  
  1202.                 else // Last column  
  1203.                 {     
  1204.                     m_stempString = m_stempString + "/"" + m_stempSql + "/"";  
  1205.                 }                 
  1206.             }  
  1207.               
  1208.             // Store the header row as the first row in memory  
  1209.             m_aRows.Add(m_stempString);  
  1210.   
  1211.             // Read and store the rest of the rows in memory  
  1212.             while (!m_rSheet->IsEOF())  
  1213.             {  
  1214.                 m_dTotalRows++; // Keep count of total number of rows  
  1215.                 try  
  1216.                 {  
  1217.                     // Get all the columns in a row  
  1218.                     m_stempString.Empty();  
  1219.                     for (short column = 0; column < m_dTotalColumns; column++)  
  1220.                     {  
  1221.                         m_rSheet->GetFieldValue(column, m_stempSql);  
  1222.   
  1223.                         // Join up all the columns into a string  
  1224.                         if (column != m_dTotalColumns-1) // Not last column  
  1225.                         {  
  1226.                             m_stempString = m_stempString + "/"" + m_stempSql + "/"" + m_sSeparator;  
  1227.                         }  
  1228.                         else // Last column  
  1229.                         {     
  1230.                             m_stempString = m_stempString + "/"" + m_stempSql + "/"";  
  1231.                         }  
  1232.                     }  
  1233.   
  1234.                     // Store the obtained row in memory  
  1235.                     m_aRows.Add(m_stempString);  
  1236.                     m_rSheet->MoveNext();  
  1237.                 }  
  1238.                 catch (...)  
  1239.                 {  
  1240.                     m_sLastError = "Error reading row/n";  
  1241.                     delete m_rSheet;  
  1242.                     m_rSheet = NULL;  
  1243.                     m_Database->Close();  
  1244.                     return false;  
  1245.                 }  
  1246.             }         
  1247.         }  
  1248.           
  1249.         m_rSheet->Close();  
  1250.         delete m_rSheet;  
  1251.         m_rSheet = NULL;  
  1252.         m_Database->Close();  
  1253.         m_dCurrentRow = 1;  
  1254.         return true;  
  1255.     }  
  1256.     else // if file is a text delimited file  
  1257.     {  
  1258.         try  
  1259.         {  
  1260.             CFile *File = NULL;  
  1261.             File = new CFile(m_sFile, CFile::modeRead | CFile::shareDenyNone);  
  1262.             if (File != NULL)  
  1263.             {  
  1264.                 CArchive *Archive = NULL;  
  1265.                 Archive = new CArchive(File, CArchive::load);  
  1266.                 if (Archive != NULL)  
  1267.                 {  
  1268.                     m_aRows.RemoveAll();  
  1269.                     // Read and store all rows in memory  
  1270.                     while(Archive->ReadString(m_stempString))  
  1271.                     {  
  1272.                         m_aRows.Add(m_stempString);  
  1273.                     }  
  1274.                     ReadRow(m_aFieldNames, 1); // Get field names i.e header row  
  1275.                     delete Archive;  
  1276.                     delete File;  
  1277.   
  1278.                     // Get total number of rows  
  1279.                     m_dTotalRows = m_aRows.GetSize();  
  1280.   
  1281.                     // Get the largest number of columns  
  1282.                     for (int i = 0; i < m_aRows.GetSize(); i++)  
  1283.                     {  
  1284.                         ReadRow(m_atempArray, i);  
  1285.                         if (m_atempArray.GetSize() > m_dTotalColumns)  
  1286.                         {  
  1287.                             m_dTotalColumns = m_atempArray.GetSize();  
  1288.                         }  
  1289.                     }  
  1290.   
  1291.                     if (m_dTotalColumns != 0)  
  1292.                     {  
  1293.                         m_bAppend = true;  
  1294.                     }  
  1295.                     return true;  
  1296.                 }  
  1297.                 delete File;  
  1298.             }  
  1299.         }  
  1300.         catch(...)  
  1301.         {  
  1302.         }  
  1303.         m_sLastError = "Error in opening file/n";  
  1304.         return false;  
  1305.     }  
  1306. }  
  1307.   
  1308. // Convert Excel column in alphabet into column number  
  1309. short CSpreadSheet::CalculateColumnNumber(CString column, bool Auto)  
  1310. {  
  1311.     if (Auto)  
  1312.     {  
  1313.         int firstLetter, secondLetter;  
  1314.         column.MakeUpper();  
  1315.   
  1316.         if (column.GetLength() == 1)  
  1317.         {  
  1318.             firstLetter = column.GetAt(0);  
  1319.             return (firstLetter - 65 + 1); // 65 is A in ascii  
  1320.         }  
  1321.         else if (column.GetLength() == 2)  
  1322.         {  
  1323.             firstLetter = column.GetAt(0);  
  1324.             secondLetter = column.GetAt(1);  
  1325.             return ((firstLetter - 65 + 1)*26 + (secondLetter - 65 + 1)); // 65 is A in ascii  
  1326.         }  
  1327.     }  
  1328.   
  1329.     // Check if it is a valid field name  
  1330.     for (int i = 0; i < m_aFieldNames.GetSize(); i++)  
  1331.     {  
  1332.         if (!column.Compare(m_aFieldNames.GetAt(i)))  
  1333.         {  
  1334.             return (i + 1);  
  1335.         }  
  1336.     }  
  1337.     m_sLastError = "Invalid field name or column alphabet/n";  
  1338.     return 0;     
  1339. }  
  1340.   
  1341. // Get the name of the Excel-ODBC driver  
  1342. void CSpreadSheet::GetExcelDriver()  
  1343. {  
  1344.     char szBuf[2001];  
  1345.     WORD cbBufMax = 2000;  
  1346.     WORD cbBufOut;  
  1347.     char *pszBuf = szBuf;  
  1348.   
  1349.     // Get the names of the installed drivers ("odbcinst.h" has to be included )  
  1350.     if(!SQLGetInstalledDrivers(szBuf,cbBufMax,& cbBufOut))  
  1351.     {  
  1352.         m_sExcelDriver = "";  
  1353.     }  
  1354.       
  1355.     // Search for the driver...  
  1356.     do  
  1357.     {  
  1358.         if( strstr( pszBuf, "Excel" ) != 0 )  
  1359.         {  
  1360.             // Found !  
  1361.             m_sExcelDriver = CString( pszBuf );  
  1362.             break;  
  1363.         }  
  1364.         pszBuf = strchr( pszBuf, '/0' ) + 1;  
  1365.     }  
  1366.     while( pszBuf[1] != '/0' );  
  1367. }  

 

由于需要对excel表格进行操作,在网上找了这个类。用odbc来实现的,具体的使用步骤基本上如下:

 CStringArray tempStrArray;

 CSpreadSheet ss(FileName, "LABLE", FALSE);
 ss.BeginTransaction();

 

 tempStrArray.RemoveAll();

 tempStrArray.Add("Item");
 tempStrArray.Add("Mac Number");
 tempStrArray.Add("RFPI Number");
 tempStrArray.Add("Serial Number");
 tempStrArray.Add("PCBA Serial Number");
 ss.AddHeaders(tempStrArray);


 tempStrArray.RemoveAll();
 tempStrArray.Add(m_strBaseSerialNo);
 tempStrArray.Add(m_strBaseSerialNo);
 tempStrArray.Add(m_strBaseMacNo);
 tempStrArray.Add(m_strHS_1_RN);
 tempStrArray.Add(m_strHS_2_RN);
 SS.AddRow(tempStrArray);
 SS.Commit();

 

先添加表头,然后再添加行,具体的控制细节可以看各函数的实现代码。

网上资料说这个类用odbc来实现对excel的操作,速度慢。而且这个类会把所有的输入都当做为字符串来处理,所以生成的单元格的内容前面都被excel强制加了个单引号前缀"'"。这是它的缺点,但总的来说,我觉得这个类还是比较好用的,就看自己的需求了。

 

说说遇到并解决的几个问题:

1.就是要在头文件中包含预编译头文件

#include "stdafx.h"

这个依据具体的工程设置而定。

2.在初始化一个excel文件的时候,表名里面不能有数字,例如不能为BS-2482.要不然的话只能添加表头,不能添加新行。现在还不知道具体原因是什么,但是大概调试看到好像是提交SQL语句的时候应该对那些数字做一定的处理。

另外,再转一篇中文文档。

CSpreadSheet中文文档
http://www.codeproject.com/info/Licenses.aspx
简介
CSpreadSheet是一个C++编写的Excel读写控件,当我们希望输出Excel文件或以文
本文件分隔 以Tab分隔的文件时, CSpreadSheet能使我们的工作事半功倍.该控件
能方便我们读写此类文件,以对象的形式供我们使用.

主要特征

创建Excel文件或文本特征文件.,写入多行或单行.读取多行,列,一行从Excel文件

或文本特征文件.替代、插入、追加到Excel文件或文本特征文件.转换已存在或最近

打开的Excel文件或文本特征文件.

限制
该控件需要MFC(微软基础类库)支持.未测试是否支持Unicode编码.控件以ODBC读写

Excel文件,需要ODBC驱动程序.Excel文件必须列标记.且首行列标记唯一(字段).禁止

删除工作簿,仅允许删除工作簿内容.列值类型参照程序数据类型.不采用Excel格式.

一,如何使用此类?


常用函数:
CSpreadSheet(CString File, CString SheetOrSeparator, bool Backup = true)
bool AddHeaders(CStringArray &FieldNames, bool replace = false)
bool AddRow(CStringArray &RowValues, long row = 0, bool replace = false)
bool AddCell(CString CellValue, short column, long row = 0)
bool AddCell(CString CellValue, CString column, long row = 0,bool Auto=true)
bool ReadRow(CStringArray &RowValues, long row = 0)
bool ReadColumn(CStringArray &ColumnValues, short column)
bool ReadColumn(CStringArray &ColumnValues, CString column,bool Auto = true)
bool ReadCell (CString &CellValue, short column, long row = 0)
bool ReadCell (CString &CellValue,CString column,long row=0,bool Auto=true)
bool DeleteSheet()
bool DeleteSheet(CString SheetName)
bool Convert(CString SheetOrSeparator)
void BeginTransaction()
bool Commit()
bool RollBack()
bool GetTransactionStatus()
void GetFieldNames (CStringArray &FieldNames)
long GetTotalRows()
short GetTotalColumns()
long GetCurrentRow()
bool GetBackupStatus()
CString GetLastError()

Excel特定函数:
bool ReplaceRows(CStringArray &NewRowValues, CStringArray &OldRowValues) 
文本函数:
尚无.

函数介绍:
CSpreadSheet(CString File, CString SheetOrSeparator, bool Backup = true)

该构造函数将打开Excel(xls)文件或其他制定工作簿的文件以供读写.创建一个CSpreadSheet对象.
参数:
File:     文件路径,可以是绝对路径或相对路径,如果文件不存在将创建一个文件.
SheetOrSeparator 工作簿名.
Backup 制定是否备份文件,默认未备份文件,如果文件存在,将创建一个名为CSpreadSheetBackup 的备份文件.

bool AddHeaders(CStringArray &FieldNames, bool replace = false)

该函数将在打开的工作簿的首行添加一个头(字段).对于Excel,每列字段必须唯一.对于特
定特征的文本文件没有限制.对于一个打开的工作簿文件,默认将添加一列,如果设置replace=true 
将替代存在的字段值.该函数返回一个Bool类型的值.对于Excel,该函数需
在添加任意行之前调用.对于特定特征的文本文件,该函数可选.
参数:
FieldNames   字段名数组.
Replace    如字段存在,该参数将决定是否替代原有字段.

bool AddRow(CStringArray &RowValues, long row = 0, bool replace = false)

该函数将追加、插入或替代一行到已经打开的文档,默认追加到行的尾部.替代将以变量的值而定,新的一行将插入或替代到指定的行.
参数:
RowValues   行值
Row    行编号,如果Row=1 第一行.即字段行.
Replace   如果该行存在,指示是否替代原有行.

bool AddCell(CString CellValue, short column, long row = 0)
bool AddCell(CString CellValue, CString column, long row = 0,bool Auto=true)
添加或替代一个打开的工作簿中的单元格,默认为该行的最后一个单元格.返回一个Bool类型的值(状态);
参数:
CellValue   填充的单元格的值。
Column   列编号
column   列名
Row    含编号,如果Row=1 第一行,即字段行.
Auto    是否让函数自动判断自动判断字段.

bool ReadRow(CStringArray &RowValues, long row = 0)

从打开的工作簿中读取一行,默认读取下一行,如果你没有使用连接池,连续运行两次,则第一次读取第一行,第二次读取第二行.返回一个Bool类型的值(状态);
参数:
RowValues   用于存储读取到的值。
Row    行编号.默认为第一行.

bool ReadColumn(CStringArray &ColumnValues, short column)
bool ReadColumn(CStringArray &ColumnValues, CString column,bool Auto = true)
从打开的工作簿中读取一列.返回一个Bool类型的值(状态);
参数:
Short column   列编号
CString column   列名或字段名.
Columnvalues   存储读取到的值.
Auto     设置函数自动扫描列名或字段.



bool ReadCell (CString &CellValue, short column, long row = 0)
bool ReadCell (CString &CellValue,CString column,long row=0,bool Auto=true)

从打开的工作簿中读取一个单元格的值。默认读取下一行.返回一个Bool类型的值(状态);
参数:
CellValue    存储单元格的值.
Short column   列编号.
Row     行编号
CString column   列名
Auto      设置函数自动扫描列名或字段.

bool DeleteSheet()
从打开的文档中删除所有的工作簿内容.返回一个Bool类型的值(状态);

bool DeleteSheet(CString SheetName)
从打开的文档中删除指定工作簿名的工作簿内容.返回一个Bool类型的值(状态);
参数:
SheetName 工作簿名.e.G Sheet1

bool Convert(CString SheetOrSeparator)
将Excel(xls)文件转换为特定特征的文本文件(.csv)或将特定特征的文本文件(.csv)转换为Excel(xls)文件.如果
将特定特征的文本文件(.csv)转换为Excel(xls)文件SheetOrSeparator将不会被使用.返回一个Bool类型的值(状态);
参数:
SheetOrSeparator 特征样式.

void BeginTransaction()
bool Commit()
bool Commit()
与SQL语言函数,函数相似,BeginTransaction开始事务,Commit提交事务.RoolBack回滚至保存点.Commit Commit将返回一个Bool值来表示是否成功.

bool GetTransactionStatus()
查询事务的状态,如果为true 表明已经开始,false表明没有开始或已经结束.

void GetFieldNames (CStringArray &FieldNames)
返回一个工作簿中的字段数组.
参数:
FieldNames 存储字段名的数组.

long GetTotalRows()
获得工作簿中行数.返回行数.

short GetTotalColumns()
获得工作簿中列数.返回列数.

long GetCurrentRow()
获得已选择的当前行的行号.返回行号,当前行将调用默认的ReadRow函数.

bool GetBackupStatus()
获得备份执行情况,true 已经执行,false没有执行(用户选择)或执行错误.

CString GetLastError()

返回最后一次错误信息.
Excel特定函数:
bool ReplaceRows(CStringArray &NewRowValues, CStringArray &OldRowValues)
该函数将搜索且代替多次执行的值.不支持已经回滚或释放的文档.执行完将返回执行的状态.
参数:

NewRowValues 新的值,即更新的值.
OldRowValues    原有的值,即已经存在的值.

示例:
// Create a new Excel spreadsheet, filename is test.xls, sheetname is TestSheet
CSpreadSheet SS("Test.xls", "TestSheet");

// Fill a sample 5 by 5 sheet
CStringArray sampleArray, testRow, Rows, Column;
CString tempString;
char alphabet = 'A';

SS.BeginTransaction();
for (int i = 1; i <= 5; i++)
{
    sampleArray.RemoveAll();
    for (int j = 1; j <= 5; j++)
    {
        tempString.Format("%c%d", alphabet++, i);
        sampleArray.Add(tempString);
    }
    alphabet = 'A';
    if (i == 1) // Add header rows
    {
        SS.AddHeaders(sampleArray);
    }
    else // Add data rows
    {
        SS.AddRow(sampleArray);
    }
}
// Set up test row for appending, inserting and replacing
for (int k = 1; k <= 5; k++)
{
    testRow.Add("Test");
}
SS.AddRow(testRow); // append test row to spreadsheet
SS.AddRow(testRow, 2); // insert test row into second row of spreadsheet
SS.AddRow(testRow, 4, true); // replace fourth row of spreadsheet with test row
SS.Committ();

SS.Convert(";"); // convert Excel spreadsheet into text delimited format 
                 // with ; as separator
// print out total number of rows
printf("Total number of rows = %d/n/n", SS.GetTotalRows()); 
// Print out entire spreadsheet
for (i = 1; i <= SS.GetTotalRows(); i++)
{
    // Read row
    SS.ReadRow(Rows, i);
    for (int j = 1; j <= Rows.GetSize(); j++)
    {
        if (j != Rows.GetSize())
        {
            printf("%s/t", Rows.GetAt(j-1));
        }
        else
        {
            printf("%s/n", Rows.GetAt(j-1));
        }
    }
}
// print out total number of columns
printf("/nTotal number of columns = %d/n/n", SS.GetTotalColumns());

// Read and print out contents of second column of spreadsheet
SS.ReadColumn(Column, 2);
for (i = 0; i < Column.GetSize(); i++)
{
    printf("Column 2 row %d: %s/n", i+1, Column.GetAt(i));
}
// Read in and print out the cell value at column 3, row 3 of spreadsheet
if (SS.ReadCell(tempString, 3, 3))
{
    printf("/nCell value at (3,3): %s/n", tempString);
}
else
{
    // print out error message if cell value cannot be read
    printf("Error: %s/n", SS.GetLastError); 
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值