在C语言中导入Excel表格数据到数据库是一个常见的需求,通常涉及Excel文件解析、数据提取以及数据库操作等步骤,以下是详细的实现方法和注意事项,涵盖环境准备、代码实现及异常处理等内容。
环境准备
- 开发工具:推荐使用Visual Studio(Windows)或GCC(Linux),确保支持C99及以上标准。
- 依赖库:
- Excel解析:需安装
libxlsxwriter
(用于生成Excel)或libxls
/OpenXLS
(用于解析旧版.xls
),新版.xlsx
文件推荐使用xlsxio
库。 - 数据库连接:根据数据库类型选择对应的C库,如MySQL用
libmysqlclient
、SQLite用sqlite3
、PostgreSQL用libpq
。 - 其他工具:需安装CMake(用于项目构建)和对应数据库的开发包(如MySQL的
libmysqlclient-dev
)。
- Excel解析:需安装
实现步骤
读取Excel文件
以.xlsx
文件为例,使用xlsxio
库解析数据:
#include <xlsxio/xlsxio.h> #include <stdio.h> void read_excel(const char* filename) { xlsxioreader xlsxioread; xlsxioread = xlsxioread_open(filename, XLSXIOREAD_SKIP_NONE); if (!xlsxioread) { perror("Failed to open Excel file"); return; } // 读取第一个工作表 xlsxioreadsheet xlsxioreadsheet = xlsxioread_sheet_open(xlsxioread, NULL, XLSXIOREAD_SKIP_NONE); if (!xlsxioreadsheet) { perror("Failed to open sheet"); xlsxioread_close(xlsxioread); return; } // 逐行读取数据 const char* row; while ((row = xlsxioread_sheet_next_row_string(xlsxioreadsheet)) != NULL) { printf("%sn", row); // 示例:直接打印行数据 } xlsxioread_sheet_close(xlsxioreadsheet); xlsxioread_close(xlsxioread); }
注意:xlsxio
需通过包管理器安装(如Ubuntu的sudo apt install libxlsxio-dev
)。
连接数据库
以MySQL为例,使用libmysqlclient
:
#include <mysql/mysql.h> MYSQL* connect_mysql(const char* host, const char* user, const char* password, const char* db) { MYSQL* mysql = mysql_init(NULL); if (!mysql) { perror("MySQL initialization failed"); return NULL; } if (!mysql_real_connect(mysql, host, user, password, db, 0, NULL, 0)) { fprintf(stderr, "Connection error: %sn", mysql_error(mysql)); mysql_close(mysql); return NULL; } return mysql; }
数据导入与处理
将Excel数据解析后插入数据库,需注意数据类型转换和SQL注入防护:
void import_data_to_mysql(MYSQL* mysql, const char* excel_file) { xlsxioreader xlsxioread = xlsxioread_open(excel_file, XLSXIOREAD_SKIP_NONE); xlsxioreadsheet xlsxioreadsheet = xlsxioread_sheet_open(xlsxioread, NULL, XLSXIOREAD_SKIP_NONE); const char* row; while ((row = xlsxioread_sheet_next_row_string(xlsxioreadsheet)) != NULL) { // 假设Excel每行包含三列:ID, Name, Age int id, age; char name[50]; if (sscanf(row, "%d,%49[^,],%d", &id, name, &age) != 3) { fprintf(stderr, "Invalid row format: %sn", row); continue; } // 使用预处理语句防止SQL注入 MYSQL_STMT* stmt = mysql_stmt_init(mysql); const char* query = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"; if (mysql_stmt_prepare(stmt, query, strlen(query)) != 0) { fprintf(stderr, "Prepare failed: %sn", mysql_stmt_error(stmt)); mysql_stmt_close(stmt); continue; } // 绑定参数 int id_param = id; char name_param[50]; strcpy(name_param, name); int age_param = age; MYSQL_BIND bind[3]; memset(bind, 0, sizeof(bind)); bind[0].buffer_type = MYSQL_TYPE_LONG; bind[0].buffer = &id_param; bind[1].buffer_type = MYSQL_TYPE_STRING; bind[1].buffer = name_param; bind[1].buffer_length = strlen(name_param); bind[2].buffer_type = MYSQL_TYPE_LONG; bind[2].buffer = &age_param; if (mysql_stmt_bind_param(stmt, bind) != 0) { fprintf(stderr, "Bind failed: %sn", mysql_stmt_error(stmt)); mysql_stmt_close(stmt); continue; } if (mysql_stmt_execute(stmt) != 0) { fprintf(stderr, "Execute failed: %sn", mysql_stmt_error(stmt)); } mysql_stmt_close(stmt); } xlsxioread_sheet_close(xlsxioreadsheet); xlsxioread_close(xlsxioread); }
主函数整合
int main() { // 1. 连接MySQL MYSQL* mysql = connect_mysql("localhost", "root", "password", "test_db"); if (!mysql) return 1; // 2. 读取Excel并导入 import_data_to_mysql(mysql, "data.xlsx"); // 3. 关闭连接 mysql_close(mysql); return 0; }
常见问题与解决方案
- Excel文件格式不支持:确保使用支持
.xlsx
的库(如xlsxio
),旧版.xls
需用libxls
。 - 数据库连接失败:检查主机地址、用户名、密码及数据库是否运行,并确认网络连通性。
- 数据类型不匹配:使用
sscanf
或strtol
等函数转换数据类型,或通过MYSQL_BIND
指定数据库字段类型。 - 内存泄漏:确保关闭所有打开的句柄(如
xlsxioread_close
、mysql_stmt_close
)。
性能优化建议
- 批量插入:使用
mysql_stmt_execute
批量提交数据,减少网络开销。 - 事务处理:通过
mysql_commit
和mysql_rollback
确保数据一致性。 - 多线程处理:对大型Excel文件,可分片读取并多线程导入(需注意线程安全)。
相关问答FAQs
Q1: 如何处理Excel中的日期格式数据?
A1: Excel日期存储为数值(如44197表示2020-12-31),需转换为YYYY-MM-DD
格式,使用mktime
或自定义函数将Excel日期戳转换为Unix时间戳,再格式化为字符串插入数据库。
Q2: 导入时如何跳过Excel表头?
A2: 在xlsxio
中,通过XLSXIOREAD_SKIP_HEADER
标志跳过首行:
xlsxioread = xlsxioread_open(filename, XLSXIOREAD_SKIP_HEADER);
或在循环中计数,跳过第一行(如if (row_count++ == 0) continue;
)。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复