C语言从Excel中读取数据的完整指南

为什么需要C语言读取Excel?

在工业自动化、金融数据分析或嵌入式系统中,C语言因其高效和底层控制能力被广泛使用。但Excel文件(.xls/.xlsx)采用二进制或OOXML格式,无法直接读取。幸运的是,有多种开源库和接口可以帮助C程序员解析Excel数据。

方案一:使用libxls读取.xls文件

libxls是专门为C/C++设计的库,可读取旧版Excel二进制文件(.xls)。首先需要安装libxls(可从 SourceForge 获取)。

安装与编译

sudo apt-get install libxls-dev  # Linux示例

代码示例

#include <xls.h>
#include <stdio.h>

int main() {
    xlsWorkBook* pWB;
    xlsWorkSheet* pWS;
    char* filename = "data.xls";
    
    pWB = xls_open(filename, "UTF-8");
    if (!pWB) { printf("Can't open file\n"); return 1; }
    
    pWS = xls_getWorkSheet(pWB, 0); // 第一张表
    xls_parseWorkSheet(pWS);
    
    for (int row = 0; row <= pWS->rows.lastrow; row++) {
        for (int col = 0; col <= pWS->rows.lastcol; col++) {
            xlsCell* cell = xls_cell(pWS, row, col);
            if (cell->str) {
                printf("%s	", cell->str);
            }
        }
        printf("\n");
    }
    
    xls_close_WS(pWS);
    xls_close_WB(pWB);
    return 0;
}

注意:libxls对中文支持较好,但只能处理.xls格式,无法读取.xlsx。

方案二:使用xlsxio读取.xlsx文件

xlsxio是一款轻量级C库,专为读取.xlsx(Open XML)设计。它基于minizip和xml2,易于集成。

下载与集成

从 GitHub 克隆项目,编译后链接 libxlsxio_read.a 和依赖库(minizip, expat等)。

代码示例

#include <xlsxio_read.h>
#include <stdio.h>

void cell_callback(int row, int col, const char* value, void* user_data) {
    printf("%s	", value ? value : "");
    if (value) free((void*)value); // 注意库要求释放
}

void row_finished(int row, void* user_data) {
    printf("\n");
}

int main() {
    xlsxioreader reader = xlsxioread_open("data.xlsx");
    if (!reader) { printf("Failed to open\n"); return 1; }
    
    xlsxioread_process(reader, "Sheet1", cell_callback, row_finished, NULL);
    xlsxioread_close(reader);
    return 0;
}

提示:xlsxio的API是回调驱动,适合流式处理大文件。

方案三:通过ODBC连接Excel

在Windows平台,C语言可通过ODBC将Excel视为数据库来查询。需要安装Microsoft Access Database Engine。

代码示例(使用unixODBC或Windows ODBC)

#include <sql.h>
#include <sqlext.h>

void queryExcel(const char* filepath) {
    SQLHENV env;
    SQLHDBC dbc;
    SQLHSTMT stmt;
    SQLRETURN ret;
    
    SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
    SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
    SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
    
    // 连接字符串
    char connStr[1024];
    sprintf(connStr, "DRIVER={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DBQ=%s;", filepath);
    ret = SQLDriverConnect(dbc, NULL, (SQLCHAR*)connStr, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
    
    if (ret != SQL_SUCCESS) { printf("Connect failed\n"); return; }
    
    SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
    SQLExecDirect(stmt, (SQLCHAR*)"SELECT * FROM [Sheet1$]", SQL_NTS);
    
    char data[256];
    while (SQLFetch(stmt) == SQL_SUCCESS) {
        SQLGetData(stmt, 1, SQL_C_CHAR, data, sizeof(data), NULL);
        printf("%s\n", data);
    }
    
    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
    SQLDisconnect(dbc);
    SQLFreeHandle(SQL_HANDLE_DBC, dbc);
    SQLFreeHandle(SQL_HANDLE_ENV, env);
}

说明:ODBC方式通用性强,但依赖驱动且效率较低,适合小型文件。

总结与建议

  • 如果只需要读取旧版.xls文件,libxls是最简单的选择。
  • 若处理新版.xlsx,推荐xlsxio(轻量)或libxls(功能丰富,但稍重)。
  • Windows环境下,ODBC可以免去外部库依赖,但代码稍复杂。
  • 注意内存管理:libxls内部管理字符串,而xlsxio需要手动释放回调中的值。
  • 跨平台性:libxls和xlsxio均支持Linux/macOS/Windows。

掌握这些方法,你就能在C项目中灵活读取Excel数据,结合其他业务逻辑大展身手。