安卓怎么安装365BET-h365官方登录平台-365batapp

简约 · 精致 · 专注内容

【史上最全】五种C语言操作Excel文件的方法全面深入指南

【史上最全】五种C语言操作Excel文件的方法全面深入指南

在C语言中操作Excel文件是一项常见且重要的任务,特别是在数据处理和科学计算领域。尽管C语言本身并不直接支持Excel文件的读写操作,但通过多种方法和技术,我们仍然可以高效地完成这项任务。本文将详细介绍几种常用的C语言操作Excel文件的方法,包括使用CSV格式、调用COM接口、使用第三方库等,并对每种方法的优缺点进行深入分析。

1. 使用CSV格式

CSV(Comma-Separated Values)是一种简单的文本格式,用于存储表格数据。通过将Excel文件另存为CSV格式,我们可以使用标准的文件操作函数来读写Excel数据。

1.1 写操作

#include

void writeExcel() {

char chy[4] = {'x', 'a', 'h', 'w'};

int data[4] = {1, 3, 6, 9};

int i;

FILE *fp = NULL;

fp = fopen("test.csv", "w");

for (i = 0; i < 4; i++) {

fprintf(fp, "%c,%d\n", chy[i], data[i]);

}

fclose(fp);

}

int main() {

writeExcel();

return 0;

}

1.2 读操作

#include

int main() {

FILE *fp;

char filename[40];

int i, j;

float da[6][5] = {0};

printf("输入文件名: ");

scanf("%s", filename);

fp = fopen(filename, "r");

for (i = 0; i < 6; i++) {

for (j = 0; j < 5; j++) {

fscanf(fp, "%f,", &da[i][j]);

}

}

for (i = 0; i < 6; i++) {

for (j = 0; j < 5; j++) {

printf("%f\t", da[i][j]);

}

printf("\n");

}

fclose(fp);

return 0;

}

优点:

简单易用:不需要额外的库或工具,只需使用标准的文件操作函数。兼容性强:可以在多种平台上使用,不受操作系统的限制。

缺点:

功能有限:不支持复杂的Excel功能,如公式、图表等。数据格式单一:无法保留原始Excel文件的样式和格式。

适用场景:

简单数据导入导出:适用于只需要导入导出简单数据的场景。数据预处理:在数据预处理阶段,可以将Excel数据转换为CSV格式,以便后续处理。

2. 调用COM接口

COM(Component Object Model)接口允许C语言程序与Excel应用程序进行交互。通过COM接口,我们可以直接操作Excel文件,执行复杂的操作。

2.1 示例代码

#include

#include

#include

void writeExcel(const char *filename) {

HRESULT hr;

CLSID clsid;

IDispatch *pXlApp = NULL;

IDispatch *pXlBooks = NULL;

IDispatch *pXlBook = NULL;

IDispatch *pXlSheet = NULL;

// 初始化COM库

CoInitialize(NULL);

// 获取Excel应用程序的CLSID

CLSIDFromProgID(L"Excel.Application", &clsid);

// 创建Excel应用程序对象

hr = CoCreateInstance(&clsid, NULL, CLSCTX_LOCAL_SERVER, &IID_IDispatch, (void **)&pXlApp);

if (FAILED(hr)) {

printf("Failed to create Excel application\n");

return;

}

// 获取工作簿集合

OLECHAR *szBooks = L"Workbooks";

DISPID dispidBooks;

hr = pXlApp->lpVtbl->GetIDsOfNames(pXlApp, &IID_NULL, &szBooks, 1, LOCALE_USER_DEFAULT, &dispidBooks);

if (FAILED(hr)) {

printf("Failed to get Workbooks ID\n");

return;

}

DISPPARAMS paramsNoArgs = {NULL, NULL, 0, 0};

VARIANT resultBooks;

hr = pXlApp->lpVtbl->Invoke(pXlApp, dispidBooks, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, ¶msNoArgs, &resultBooks, NULL, NULL);

if (FAILED(hr)) {

printf("Failed to get Workbooks\n");

return;

}

pXlBooks = resultBooks.pdispVal;

// 创建一个新的工作簿

OLECHAR *szAdd = L"Add";

DISPID dispidAdd;

hr = pXlBooks->lpVtbl->GetIDsOfNames(pXlBooks, &IID_NULL, &szAdd, 1, LOCALE_USER_DEFAULT, &dispidAdd);

if (FAILED(hr)) {

printf("Failed to get Add ID\n");

return;

}

VARIANT resultBook;

hr = pXlBooks->lpVtbl->Invoke(pXlBooks, dispidAdd, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶msNoArgs, &resultBook, NULL, NULL);

if (FAILED(hr)) {

printf("Failed to add Workbook\n");

return;

}

pXlBook = resultBook.pdispVal;

// 获取第一个工作表

OLECHAR *szSheets = L"Worksheets";

DISPID dispidSheets;

hr = pXlBook->lpVtbl->GetIDsOfNames(pXlBook, &IID_NULL, &szSheets, 1, LOCALE_USER_DEFAULT, &dispidSheets);

if (FAILED(hr)) {

printf("Failed to get Worksheets ID\n");

return;

}

VARIANT resultSheets;

hr = pXlBook->lpVtbl->Invoke(pXlBook, dispidSheets, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, ¶msNoArgs, &resultSheets, NULL, NULL);

if (FAILED(hr)) {

printf("Failed to get Worksheets\n");

return;

}

IDispatch *pXlSheets = resultSheets.pdispVal;

OLECHAR *szItem = L"Item";

DISPID dispidItem;

hr = pXlSheets->lpVtbl->GetIDsOfNames(pXlSheets, &IID_NULL, &szItem, 1, LOCALE_USER_DEFAULT, &dispidItem);

if (FAILED(hr)) {

printf("Failed to get Item ID\n");

return;

}

VARIANT index;

index.vt = VT_I4;

index.lVal = 1;

DISPPARAMS paramsItem = {&index, NULL, 1, 0};

VARIANT resultSheet;

hr = pXlSheets->lpVtbl->Invoke(pXlSheets, dispidItem, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, ¶msItem, &resultSheet, NULL, NULL);

if (FAILED(hr)) {

printf("Failed to get Worksheet\n");

return;

}

pXlSheet = resultSheet.pdispVal;

// 写入数据

OLECHAR *szCells = L"Cells";

DISPID dispidCells;

hr = pXlSheet->lpVtbl->GetIDsOfNames(pXlSheet, &IID_NULL, &szCells, 1, LOCALE_USER_DEFAULT, &dispidCells);

if (FAILED(hr)) {

printf("Failed to get Cells ID\n");

return;

}

VARIANT row, col;

row.vt = VT_I4;

col.vt = VT_I4;

row.lVal = 1;

col.lVal = 1;

DISPPARAMS paramsCell = {&row, &col, 2, 0};

VARIANT resultCell;

hr = pXlSheet->lpVtbl->Invoke(pXlSheet, dispidCells, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, ¶msCell, &resultCell, NULL, NULL);

if (FAILED(hr)) {

printf("Failed to get Cell\n");

return;

}

IDispatch *pXlCell = resultCell.pdispVal;

OLECHAR *szValue = L"Value";

DISPID dispidValue;

hr = pXlCell->lpVtbl->GetIDsOfNames(pXlCell, &IID_NULL, &szValue, 1, LOCALE_USER_DEFAULT, &dispidValue);

if (FAILED(hr)) {

printf("Failed to get Value ID\n");

return;

}

VARIANT value;

value.vt = VT_BSTR;

value.bstrVal = SysAllocString(L"Hello, World!");

DISPPARAMS paramsValue = {&value, NULL, 1, 0};

hr = pXlCell->lpVtbl->Invoke(pXlCell, dispidValue, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, ¶msValue, NULL, NULL, NULL);

if (FAILED(hr)) {

printf("Failed to set Cell Value\n");

return;

}

// 保存并关闭

OLECHAR *szSaveAs = L"SaveAs";

DISPID dispidSaveAs;

hr = pXlBook->lpVtbl->GetIDsOfNames(pXlBook, &IID_NULL, &szSaveAs, 1, LOCALE_USER_DEFAULT, &dispidSaveAs);

if (FAILED(hr)) {

printf("Failed to get SaveAs ID\n");

return;

}

VARIANT filename;

filename.vt = VT_BSTR;

filename.bstrVal = SysAllocString(L"output.xlsx");

DISPPARAMS paramsSaveAs = {&filename, NULL, 1, 0};

hr = pXlBook->lpVtbl->Invoke(pXlBook, dispidSaveAs, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶msSaveAs, NULL, NULL, NULL);

if (FAILED(hr)) {

printf("Failed to save Workbook\n");

return;

}

OLECHAR *szQuit = L"Quit";

DISPID dispidQuit;

hr = pXlApp->lpVtbl->GetIDsOfNames(pXlApp, &IID_NULL, &szQuit, 1, LOCALE_USER_DEFAULT, &dispidQuit);

if (FAILED(hr)) {

printf("Failed to get Quit ID\n");

return;

}

hr = pXlApp->lpVtbl->Invoke(pXlApp, dispidQuit, &IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶msNoArgs, NULL, NULL, NULL);

if (FAILED(hr)) {

printf("Failed to quit Excel application\n");

return;

}

// 释放资源

VariantClear(&value);

SysFreeString(szValue);

VariantClear(&row);

VariantClear(&col);

VariantClear(&resultCell);

VariantClear(&resultSheet);

VariantClear(&resultSheets);

VariantClear(&resultBook);

VariantClear(&resultBooks);

VariantClear(&index);

VariantClear(¶msCell);

VariantClear(¶msItem);

VariantClear(¶msValue);

VariantClear(¶msNoArgs);

pXlCell->lpVtbl->Release(pXlCell);

pXlSheet->lpVtbl->Release(pXlSheet);

pXlSheets->lpVtbl->Release(pXlSheets);

pXlBook->lpVtbl->Release(pXlBook);

pXlBooks->lpVtbl->Release(pXlBooks);

pXlApp->lpVtbl->Release(pXlApp);

CoUninitialize();

}

int main() {

writeExcel("output.xlsx");

return 0;

}

优点:

功能强大:支持复杂的Excel功能,如公式、图表等。直接操作:可以直接操作Excel应用程序,实现高级功能。

缺点:

代码复杂:需要处理大量的COM接口调用,代码复杂度较高。依赖性强:依赖于Windows操作系统和Excel应用程序,不适用于其他平台。

适用场景:

高级操作:需要直接操作Excel应用程序的场景,如生成图表、执行宏等。复杂需求:需要实现复杂功能,如数据验证、条件格式等。

3. 使用第三方库

使用第三方库是另一种高效的操作Excel文件的方法。这些库提供了丰富的API,简化了操作步骤。

3.1 使用libxlsxwriter库

libxlsxwriter 是一个开源库,用于创建Excel XLSX文件。

3.1.1 安装

sudo apt-get install libxlsxwriter-dev

3.1.2 示例代码

#include "xlsxwriter.h"

void writeExcel(const char *filename) {

lxw_workbook *workbook = workbook_new(filename);

lxw_worksheet *worksheet = workbook_add_worksheet(workbook, NULL);

// 写入数据

worksheet_write_string(worksheet, 0, 0, "Hello, World!", NULL);

worksheet_write_number(worksheet, 1, 0, 123.45, NULL);

// 关闭工作簿

workbook_close(workbook);

}

int main() {

writeExcel("output.xlsx");

return 0;

}

3.2 使用libxls库

libxls 是一个用于读取Excel XLS文件的库。

3.2.1 安装

sudo apt-get install libxls-dev

3.2.2 示例代码

#include

#include

void readExcel(const char *filename) {

xlsWorkBook *workbook = xls_open(filename, "UTF-8");

if (workbook == NULL) {

printf("Failed to open the file.\n");

return;

}

for (int i = 0; i < workbook->sheets.count; ++i) {

xlsWorkSheet *sheet = xls_getWorkSheet(workbook, i);

xls_parseWorkSheet(sheet);

for (int row = 0; row <= sheet->rows.lastrow; ++row) {

for (int col = 0; col <= sheet->rows.lastcol; ++col) {

xlsCell *cell = xls_cell(sheet, row, col);

if (cell && cell->str) {

printf("Row %d, Col %d: %s\n", row, col, cell->str);

}

}

}

xls_close_WS(sheet);

}

xls_close_WB(workbook);

}

int main() {

readExcel("input.xls");

return 0;

}

3.3 使用libxlsxreader库

libxlsxreader 是一个用于读取Excel XLSX文件的库。

3.3.1 安装

sudo apt-get install libxlsxreader-dev

3.3.2 示例代码

#include

#include

void readExcel(const char *filename) {

lxw_reader *reader = reader_new(filename);

if (reader == NULL) {

printf("Failed to open the file.\n");

return;

}

int num_sheets = reader_get_num_sheets(reader);

printf("Number of sheets: %d\n", num_sheets);

for (int i = 0; i < num_sheets; i++) {

lxw_worksheet *worksheet = reader_get_worksheet(reader, i);

int rows = worksheet_get_row_count(worksheet);

int cols = worksheet_get_col_count(worksheet);

printf("Sheet %d: %d rows, %d columns\n", i + 1, rows, cols);

for (int row = 0; row < rows; row++) {

for (int col = 0; col < cols; col++) {

lxw_cell *cell = worksheet_get_cell(worksheet, row, col);

if (cell) {

const char *value = cell_get_value(cell);

printf("Row %d, Column %d: %s\n", row, col, value);

}

}

}

}

reader_free(reader);

}

int main() {

readExcel("input.xlsx");

return 0;

}

优点:

API丰富:提供了丰富的API,简化了操作步骤。支持多种格式:支持多种Excel文件格式,包括XLS和XLSX。

缺点:

依赖库:需要安装额外的库,增加了项目的依赖。兼容性问题:可能存在兼容性问题,特别是对于某些特殊的Excel文件。

适用场景:

多格式支持:需要处理多种Excel文件格式的场景。高效读写:需要高效读写大量数据的场景。

4. 使用API接口

除了上述方法,还可以通过API接口(如Microsoft Excel API、Google Sheets API等)来操作Excel文件。

4.1 使用Microsoft Excel API

4.1.1 示例代码

#include

#include

#include

#include

#define ACCESS_TOKEN "YOUR_ACCESS_TOKEN"

#define EXCEL_FILE_ID "YOUR_EXCEL_FILE_ID"

void readExcel() {

CURL *curl;

CURLcode res;

curl_global_init(CURL_GLOBAL_DEFAULT);

curl = curl_easy_init();

if (curl) {

char url[256];

snprintf(url, sizeof(url), "https://graph.microsoft.com/v1.0/me/drive/items/%s/workbook/worksheets", EXCEL_FILE_ID);

struct curl_slist *headers = NULL;

headers = curl_slist_append(headers, "Authorization: Bearer " ACCESS_TOKEN);

curl_easy_setopt(curl, CURLOPT_URL, url);

curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

res = curl_easy_perform(curl);

if (res != CURLE_OK) {

fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));

}

curl_slist_free_all(headers);

curl_easy_cleanup(curl);

}

curl_global_cleanup();

}

int main() {

readExcel();

return 0;

}

优点:

远程操作:支持远程操作Excel文件,适用于分布式系统。功能丰富:提供丰富的接口,可以实现复杂的功能。

缺点:

网络依赖:需要网络连接,依赖于API服务的可用性。开发难度:需要进行身份验证和授权,增加了开发难度。

适用场景:

远程操作:需要远程操作Excel文件的场景。分布式系统:分布式系统中需要协同操作Excel文件的场景。

5. 直接解析Excel文件格式

直接解析Excel文件格式是一项复杂的任务,因为Excel文件格式(尤其是XLSX)非常复杂,并且包含了大量的元数据和压缩数据。不过,理解基本的文件格式对于某些特殊需求可能是必要的。

5.1 解析XLS文件

XLS文件格式是二进制格式,解析起来相对复杂。一般来说,不建议手动解析XLS文件,除非有非常特殊的需求。

5.2 解析XLSX文件

XLSX文件实际上是一个压缩包,里面包含了多个XML文件。这些XML文件描述了工作表的数据、样式、关系等信息。

5.2.1 示例代码

#include

#include

#include

#include

#include

#include

void parseXLSX(const char *filename) {

struct zip *z = zip_open(filename, 0, NULL);

if (!z) {

fprintf(stderr, "Failed to open zip file\n");

return;

}

struct zip_stat st;

zip_stat_init(&st);

zip_stat(z, "xl/worksheets/sheet1.xml", 0, &st);

struct zip_file *zf = zip_fopen(z, "xl/worksheets/sheet1.xml", 0);

if (!zf) {

fprintf(stderr, "Failed to open sheet1.xml\n");

zip_close(z);

return;

}

char *contents = malloc(st.size);

zip_fread(zf, contents, st.size);

zip_fclose(zf);

xmlDocPtr doc = xmlReadMemory(contents, st.size, "sheet1.xml", NULL, 0);

if (doc == NULL) {

fprintf(stderr, "Failed to parse XML\n");

free(contents);

zip_close(z);

return;

}

xmlNodePtr root = xmlDocGetRootElement(doc);

if (root == NULL) {

fprintf(stderr, "Empty document\n");

xmlFreeDoc(doc);

free(contents);

zip_close(z);

return;

}

xmlNodePtr node = root->children;

while (node != NULL) {

if (xmlStrcmp(node->name, (const xmlChar *)"sheetData") == 0) {

xmlNodePtr rowNode = node->children;

while (rowNode != NULL) {

if (xmlStrcmp(rowNode->name, (const xmlChar *)"row") == 0) {

xmlNodePtr cellNode = rowNode->children;

while (cellNode != NULL) {

if (xmlStrcmp(cellNode->name, (const xmlChar *)"c") == 0) {

xmlChar *value = xmlGetProp(cellNode, (const xmlChar *)"v");

if (value) {

printf("%s\t", value);

xmlFree(value);

}

}

cellNode = cellNode->next;

}

printf("\n");

}

rowNode = rowNode->next;

}

}

node = node->next;

}

xmlFreeDoc(doc);

free(contents);

zip_close(z);

}

int main() {

parseXLSX("input.xlsx");

return 0;

}

优点:

自主控制:不依赖于第三方库,完全自主控制。高度定制:可以处理复杂的文件格式和元数据。

缺点:

实现复杂:需要深入了解Excel文件格式,实现复杂。开发成本高:开发和维护成本高,不适合简单的项目需求。

适用场景:

特殊需求:需要高度定制的解析逻辑,适用于特殊需求。高性能要求:避免依赖第三方库的性能瓶颈,适用于高性能要求的场景。

6. 结论

通过上述介绍,我们可以看到C语言操作Excel文件有多种方法,每种方法都有其适用场景和优缺点。选择合适的方法取决于具体的项目需求和开发环境:

CSV格式:适用于简单的需求,不需要复杂的Excel功能。COM接口:适用于需要直接操作Excel应用程序的场景,但依赖于Windows操作系统。第三方库:提供了丰富的API,简化了操作步骤,适用于大多数场景。API接口:支持远程操作Excel文件,适用于分布式系统。直接解析Excel文件格式:适用于特殊需求,需要高度定制的解析逻辑。

希望本文能帮助你在C语言中高效地操作Excel文件,满足不同的开发需求。无论你是初学者还是经验丰富的开发者,都能找到适合自己的方法,提高开发效率和代码质量。

相关推荐

四川宜宾有一处世界奇观叫“僰人悬棺”,你知道什么是“僰人”吗
当当网和亚马逊买书哪个好 亚马逊和当当网哪个买书比较优惠
康熙字典躾的解释

康熙字典躾的解释

h365官方登录平台 08-15
帶熹字成語,熹的成語,含有熹字的成語,熹字四字成語大全
《中国有嘻哈》鬼卞哭了!摘下渔夫帽他还是一位老师
灯泡怎么检验?灯泡检验方法与标准指南