henrikatwork
asked on
Reading from an Excel file (ODBC?)
Hello experts,
I am trying to add a "import from excel"-feature to my C++ application.
I thought it would be a simple task of traversing a couple of cells with an easy-to-use API.
However, as the project is built with standard C++ (no .net or mfc!) the only viable way seems to be using
the rather clumsy ODBC-approach. (I already tossed the idea of making this feature cross platform out the window)
I found this link on the subject:
http://www.codeproject.com/database/excel_odbc.asp
Unforunately, that code is closely tied to MFC. Also it just pulls names like "demo_table" and "field_1"
out of thin air!
As I've managed to get something similar (Plain-C ODBC) working when reading data from an Access database,
Im supposing doing the same thing with an excel-sheet will be much of the same, except this time I don't
know the name of the sheets and fields.
Im looking for C/C++ code examples to read a couple of cells from a an Excel-sheet (Just reading, no writing).
I would appreciate if somebody could supply that, or provide a link to a website who does.
(Im not interested in having the user manually export the .xls file to a xml or comma-separated text file,
so you don't have to bother suggesting that, unless that can be made automatically without user interaction)
Regards,
Henrik
I am trying to add a "import from excel"-feature to my C++ application.
I thought it would be a simple task of traversing a couple of cells with an easy-to-use API.
However, as the project is built with standard C++ (no .net or mfc!) the only viable way seems to be using
the rather clumsy ODBC-approach. (I already tossed the idea of making this feature cross platform out the window)
I found this link on the subject:
http://www.codeproject.com/database/excel_odbc.asp
Unforunately, that code is closely tied to MFC. Also it just pulls names like "demo_table" and "field_1"
out of thin air!
As I've managed to get something similar (Plain-C ODBC) working when reading data from an Access database,
Im supposing doing the same thing with an excel-sheet will be much of the same, except this time I don't
know the name of the sheets and fields.
Im looking for C/C++ code examples to read a couple of cells from a an Excel-sheet (Just reading, no writing).
I would appreciate if somebody could supply that, or provide a link to a website who does.
(Im not interested in having the user manually export the .xls file to a xml or comma-separated text file,
so you don't have to bother suggesting that, unless that can be made automatically without user interaction)
Regards,
Henrik
ASKER
Sorry, I've already seen that and its not really what im looking for.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
BTW, with that one, you could even reconsider to make that feature cross-platform *g*
After you exported the contents to a .csv file by using the link jkr gave you, it is easy to read and parse the file like that:
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
struct Record
{
string col1;
int col2;
double col3;
// ...
enum { COL1, COL2, COL3, MAX_COLS };
};
bool getDataFromCsv(const string& csvfile, vector<Record>& arr)
{
ifstream ifs(csvfile.c_str());
if (!ifs) return false;
string line;
while (getline(ifs, line))
{
// a .csv file separates each column entry by ; (default)
int pos = 0;
int lpos = 0;
int col = 0;
line += ';'; // add a semicolon at end of line
Record rec;
while ((pos = line.find(';', lpos)) != string::npos)
{
string entry = line.substr(lpos, pos - lpos);
switch(col)
{
case COL1:
rec.col1 = entry;
break;
case COL2:
{
istringstream iss(entry);
iss >> rec.col2;
if (!iss) // wrong integer
return false;
break;
}
case COL3:
istringstream iss(entry);
iss >> rec.col3;
if (!iss) // wrong double
return false;
break;
default:
return false; // too many columns
}
arr.push_back(rec);
col++;
}
}
ifs.close();
return true;
}
Regards, Alex
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
struct Record
{
string col1;
int col2;
double col3;
// ...
enum { COL1, COL2, COL3, MAX_COLS };
};
bool getDataFromCsv(const string& csvfile, vector<Record>& arr)
{
ifstream ifs(csvfile.c_str());
if (!ifs) return false;
string line;
while (getline(ifs, line))
{
// a .csv file separates each column entry by ; (default)
int pos = 0;
int lpos = 0;
int col = 0;
line += ';'; // add a semicolon at end of line
Record rec;
while ((pos = line.find(';', lpos)) != string::npos)
{
string entry = line.substr(lpos, pos - lpos);
switch(col)
{
case COL1:
rec.col1 = entry;
break;
case COL2:
{
istringstream iss(entry);
iss >> rec.col2;
if (!iss) // wrong integer
return false;
break;
}
case COL3:
istringstream iss(entry);
iss >> rec.col3;
if (!iss) // wrong double
return false;
break;
default:
return false; // too many columns
}
arr.push_back(rec);
col++;
}
}
ifs.close();
return true;
}
Regards, Alex
ASKER
Automatically export the file to cvs? I like the idea... but I can't have the external dependency of perl! (atleast not on windows) Especially not when the script depends on the following modules:
Locale::Recode
Unicode::Map
Spreadsheet::ParseExcel
Spreadsheet::ParseExcel::F mtUnicode (should be included with Spreadsheet::ParseExcel)
Text::CSV_XS
I found this application:
http://www.indigostar.com/perl2exe.htm
But it costs money.
What would do is either something that (easily) compiled the perl script, or a similar utility written i C... Or back to the ODBC-approach.
Locale::Recode
Unicode::Map
Spreadsheet::ParseExcel
Spreadsheet::ParseExcel::F
Text::CSV_XS
I found this application:
http://www.indigostar.com/perl2exe.htm
But it costs money.
What would do is either something that (easily) compiled the perl script, or a similar utility written i C... Or back to the ODBC-approach.
>>>> Automatically export the file to cvs? I like the idea
You might use a vbscribt like the one that can be found at http://www.codecomments.com/archive305-2006-4-897480.html.
You could do automation in C++ as well but it would be really hard work while it is relatively simple using VB.
Simply start the vbscript by
WinExec("xls2csv.vbs", SW_HIDE);
Regards, Alex
You might use a vbscribt like the one that can be found at http://www.codecomments.com/archive305-2006-4-897480.html.
You could do automation in C++ as well but it would be really hard work while it is relatively simple using VB.
Simply start the vbscript by
WinExec("xls2csv.vbs", SW_HIDE);
Regards, Alex
ASKER
Hello Alex,
Your vb-script solution actually works! Well, not on my computer that didn't have excel installed... I suppose it uses the excel-odbc driver?
Anyway, common sense says that i should split the points between you and jkr (400/100 maybe?)
However as this is a 500pt questions I've decided to push my luck a little further...
1) WinExec didn't work as it is can only used for .exe files (?) I got it working with ShellExecute. So the question is: How do i halt the progress of my c++ application until the script has finished executing?
2) (More of a vb-script question) The script pops up an annoying "Function XLS2CVS = FALSE/TRUE" messagebox at the end, how do i get rid of it?
3) (vb-script) How do I pass parameters to the script? For instance the path to the .xls file and the .csv output file?
Actually none of these questions have anything to do with C++ (especially not 2 and 3, which I could ask in the vb-script forum)
Your vb-script solution actually works! Well, not on my computer that didn't have excel installed... I suppose it uses the excel-odbc driver?
Anyway, common sense says that i should split the points between you and jkr (400/100 maybe?)
However as this is a 500pt questions I've decided to push my luck a little further...
1) WinExec didn't work as it is can only used for .exe files (?) I got it working with ShellExecute. So the question is: How do i halt the progress of my c++ application until the script has finished executing?
2) (More of a vb-script question) The script pops up an annoying "Function XLS2CVS = FALSE/TRUE" messagebox at the end, how do i get rid of it?
3) (vb-script) How do I pass parameters to the script? For instance the path to the .xls file and the .csv output file?
Actually none of these questions have anything to do with C++ (especially not 2 and 3, which I could ask in the vb-script forum)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
>>>> #include <string.h>
replace that by
#include <string>
using namespace std;
I copied it from an older source which included old string header.
Regards, Alex
replace that by
#include <string>
using namespace std;
I copied it from an older source which included old string header.
Regards, Alex
ASKER
Well deserved points... thanks Alex!
#import "C:\Program Files\Microsoft Office\Office\MSO9.DLL"
#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OL
#import "C:\Program Files\Microsoft Office\Office\EXCEL9.OLB" \
rename("DialogBox", "ExcelDialogBox") \
rename("RGB", "ExcelRGB") \
no_dual_interfaces
using namespace std;
int main()
{
// Initialize COM
CoInitialize(NULL);
try
{
Excel::_ApplicationPtr excel;
// Initialize Excel and make sure it's initialized
HRESULT hr = excel.CreateInstance(L"Exc
if(FAILED(hr))
{
char msg[1024] = {0};
sprintf(msg, "E: There was an error initializing Excel: %d", hr);
throw std::runtime_error(msg);
}
Excel::_WorkbookPtr workbook = excel->Workbooks->Add(stat
Excel::_WorksheetPtr worksheet = excel->ActiveSheet; // Get the active sheet
worksheet->Open("whatever"
// This is how you put the values into the worksheet
worksheet->Range["A1"]->Va
worksheet->Save();
workbook->Close(); // Close the workbook
excel->Quit(); // Quit excel
}
catch(_com_error &ce)
{
// Handle the error
}
CoUninitialize();
return 0;
}
Hope this helps...
Mactep.