在C语言中操作Excel表格并将其导入数据库,通常需要借助第三方库来实现,因为标准C语言库本身不直接支持Excel文件的读写和数据库连接,常见的方案包括使用ODBC(开放数据库连接)结合Excel驱动,或者使用专门的Excel操作库如libxlsxwriter、libxls等,再通过数据库API(如MySQL Connector、SQLite3等)将数据存入数据库,以下将详细介绍具体实现步骤和代码示例。
环境准备与依赖安装
Excel操作库选择
- 对于.xlsx格式(Excel 2007及以上),推荐使用
libxlsxwriter
或OpenXLSX
(C++库,可通过C接口调用)。 - 对于.xls格式(Excel 2003及更早),可使用
libxls
。 - 示例以
libxlsxwriter
为例,需先下载安装:从GitHub获取源码,编译安装sudo make install
。
- 对于.xlsx格式(Excel 2007及以上),推荐使用
数据库连接库
- 以SQLite3为例(轻量级,无需额外服务),下载
sqlite3.h
和libsqlite3.a
并配置项目路径。 - 若使用MySQL,需安装
mysql-connector-c
。
- 以SQLite3为例(轻量级,无需额外服务),下载
ODBC方式(通用方案)
- 配置ODBC数据源:在Windows中通过“ODBC数据源管理器”添加Excel驱动,设置数据源名称(DSN)和Excel文件路径。
- Linux下需安装
unixODBC
和odbc-jdbc
驱动,并配置odbc.ini
。
通过libxlsxwriter读取Excel数据
以下是读取Excel文件并解析数据的代码片段:
#include "xlsxwriter.h" #include <stdio.h> void read_excel(const char *filename) { lxw_workbook *workbook = workbook_open(filename); lxw_worksheet *worksheet = workbook_get_worksheet_by_name(workbook, "Sheet1"); if (!worksheet) { printf("Worksheet not found.n"); workbook_close(workbook); return; } int rows = worksheet_get_dim_rows(worksheet); int cols = worksheet_get_dim_cols(worksheet); for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { lxw_cell_value *cell = worksheet_read_cell(worksheet, row, col); if (cell->type == LXW_CELL_TYPE_NUMBER) { printf("%gt", cell->value.number); } else if (cell->type == LXW_CELL_TYPE_STRING) { printf("%st", cell->value.string); } } printf("n"); } workbook_close(workbook); }
注意:libxlsxwriter
主要用于写入,读取需结合其他库如OpenXLSX
或直接解析文件格式(较复杂),实际项目中可考虑调用Python脚本(通过popen
)或使用C++库。
通过ODBC读取Excel并导入数据库
以下是ODBC方式读取Excel并插入SQLite3的示例代码:
#include <sql.h> #include <sqlext.h> #include <sqlite3.h> void excel_to_db_via_odbc(const char *excel_path, const char *db_path) { SQLHENV env; SQLHDBC dbc; SQLHSTMT stmt; // 初始化ODBC环境 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); // 连接Excel数据源(需提前配置DSN) char conn_str[256]; sprintf(conn_str, "DSN=ExcelDSN;Database=%s", excel_path); SQLDriverConnect(dbc, NULL, (SQLCHAR*)conn_str, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE); // 执行查询 SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); SQLExecDirect(stmt, (SQLCHAR*)"SELECT * FROM [Sheet1$]", SQL_NTS); // 绑定列(示例:假设两列,第一列字符串,第二列整数) SQLCHAR col1_data[256]; SQLLEN col1_len; SQLINTEGER col2_data; SQLBindCol(stmt, 1, SQL_C_CHAR, col1_data, sizeof(col1_data), &col1_len); SQLBindCol(stmt, 2, SQL_C_SLONG, &col2_data, 0, NULL); // 插入SQLite数据库 sqlite3 *db; sqlite3_open(db_path, &db); sqlite3_stmt *insert_stmt; sqlite3_prepare_v2(db, "INSERT INTO excel_data (col1, col2) VALUES (?, ?)", -1, &insert_stmt, NULL); while (SQLFetch(stmt) == SQL_SUCCESS) { sqlite3_bind_text(insert_stmt, 1, (const char*)col1_data, -1, SQLITE_STATIC); sqlite3_bind_int(insert_stmt, 2, col2_data); sqlite3_step(insert_stmt); sqlite3_reset(insert_stmt); } // 释放资源 SQLFreeHandle(SQL_HANDLE_STMT, stmt); SQLDisconnect(dbc); SQLFreeHandle(SQL_HANDLE_DBC, dbc); SQLFreeHandle(SQL_HANDLE_ENV, env); sqlite3_finalize(insert_stmt); sqlite3_close(db); }
完整流程与注意事项
- 数据映射:Excel列需与数据库表结构匹配,可通过动态SQL或预定义表结构实现。
- 性能优化:批量插入(如SQLite的
exec
执行多条语句)可减少IO开销。 - 错误处理:需检查SQL返回值(如
SQLFetch
、sqlite3_step
)并处理异常。 - 跨平台兼容性:ODBC在Linux下配置较复杂,Windows更简便;纯C方案需处理不同Excel版本的格式差异。
相关问答FAQs
Q1: 如何处理Excel中的日期类型数据?
A: Excel日期存储为数值(如44197代表2020/12/31),读取后需通过mktime
或自定义函数转换为Unix时间戳。
time_t excel_date_to_time(double excel_date) { time_t rawtime = (excel_date - 25569) * 86400; // Excel起始日期为1900/1/1 return rawtime; }
Q2: 大数据量导入时如何避免内存溢出?
A: 采用分批次读取和插入策略,例如每次读取1000行后执行一次数据库提交,对于SQLite,可设置PRAGMA synchronous=OFF
提高写入速度,但需权衡数据安全性。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复