Well... that's it.
I need something simple and reliable (doesn't have to have fancy features - I need to write and read text and numbers from Excel cells)
And yes, I would like a sample "Hello Cell" code...
What do you recommend?
Well... that's it.
I need something simple and reliable (doesn't have to have fancy features - I need to write and read text and numbers from Excel cells)
And yes, I would like a sample "Hello Cell" code...
What do you recommend?
SpreadsheetGear for .NET will do it. You can see what people say and download the free trial to run this code:
namespace HelloCell
{
class Program
{
static void Main(string[] args)
{
// Create a new empty workbook.
SpreadsheetGear.IWorkbook workbook = SpreadsheetGear.Factory.GetWorkbook();
// Set the worksheet name.
SpreadsheetGear.IWorksheet worksheet = workbook.Worksheets[0];
worksheet.Name = "HelloSheet";
// Add a text cell.
worksheet.Cells["A1"].Value = "Hello Cell";
// Save as Excel 97-2003 xls workbook.
workbook.SaveAs("HelloWorkbook.xls", SpreadsheetGear.FileFormat.Excel8);
// Save as Excel 2007 xlsx (Open XML) workbook.
workbook.SaveAs("HelloWorkbook.xlsx", SpreadsheetGear.FileFormat.OpenXMLWorkbook);
// Now load it back in.
workbook = SpreadsheetGear.Factory.GetWorkbook("HelloWorkbook.xlsx");
// Write cell A1 to the console.
System.Console.WriteLine("A1='{0}'", workbook.Worksheets["HelloSheet"].Cells["A1"].Value);
}
}
}
Strongly discouraged. I'd recommend using a C-friendly format (e.g. CSVs) instead of XLS, or using the new XML formats (take your pick on XML and ZIP libraries).
Still, for a quick fix, you could export to quoted CSV and then import using VBScript. Something like this, although I'd try to get it to work in VBA first.
Note that this will require a copy of Office, and will not scale well (but you can hide the Excel window).
I've just found xlsLib, so if you really need to write directly in C, give it a go! Be careful though, because it's very hard to get right, especially if you're writing to already-existing files.
There also exists LibExcel, but that's C++, so you'd need to compile a wrapper around, or rewrite for C.
One final caveat: the reason I didn't search for these at the start is that it's extremely difficult to get right. I have not used the libraries above, but I suspect they'll break in strange and unusual ways. I trust you've read Joel's take on the Office formats.
Excel, like other Office products, exports its guts over COM. This is available for use in C++, VB, C#, and whatever other languages have COM interop -- provided that you're running in Windows and have Excel installed. (You can't get to COM from plain C. Whether this is fortunate or unfortunate is up to you.)
COM is a bloody messy pain for unmanaged languages, though. The following VB:
Set objExcel = CreateObject("Excel.Application") ' start or use existing Excel
objExcel.Visible = True ' show the window
objExcel.Workbooks.Add ' create an empty workbook
roughly translates into the following C++:
#include <assert.h>
#include <ole2.h>
#include <tchar.h>
int main() {
HRESULT hr;
IDispatch *objExcel, *objWorkbooks;
CLSID clsid;
DISPID id, id2;
DISPPARAMS p;
VARIANT v;
TCHAR *name;
CoInitialize(NULL);
hr = CLSIDFromProgID(_T("Excel.Application"), &clsid);
assert(SUCCEEDED(hr));
hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER,
IID_IDispatch, (LPVOID *)&objExcel);
assert(SUCCEEDED(hr));
id2 = DISPID_PROPERTYPUT;
name = _T("Visible");
hr = objExcel->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &id);
assert(SUCCEEDED(hr));
VariantInit(&v);
v.vt = VT_I4;
v.lVal = 1;
p.cArgs = 1;
p.rgvarg = &v;
p.cNamedArgs = 1;
p.rgdispidNamedArgs = &id2;
hr = objExcel->Invoke(id, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYPUT, &p, NULL, NULL, NULL);
assert(SUCCEEDED(hr));
name = _T("Workbooks");
hr = objExcel->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &id);
assert(SUCCEEDED(hr));
p.cArgs = 0;
p.rgvarg = NULL;
p.cNamedArgs = 0;
p.rgdispidNamedArgs = NULL;
hr = objExcel->Invoke(id, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, &p, &v, NULL, NULL);
assert(SUCCEEDED(hr));
objWorkbooks = v.pdispVal;
name = _T("Add");
hr = objWorkbooks->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &id);
assert(SUCCEEDED(hr));
p.cArgs = 0;
p.rgvarg = NULL;
p.cNamedArgs = 0;
p.rgdispidNamedArgs = NULL;
hr = objWorkbooks->Invoke(id, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYGET, &p, NULL, NULL, NULL);
assert(SUCCEEDED(hr));
return 0;
}
I've a small extension to the stuff ephemient has posted. There's very handy library available with eases the paind with the IDispatch interface. http://disphelper.sourceforge.net/
It's just one file you add to your projects but it makes IDispatch programming with C nearly fun ;-)