• 【C++】使用VS2022和GCC编译Xlnt库读取EXCEL


    目的

    因为有需求需要在PC上读取Excel文件,而且得要用C++来实现,故在Github上寻找了下好使的库,于是乎找到了Xlnt库
    https://github.com/tfussell/xlnt
    我采取了两个编译器VS2022和GCC10分别编译成库,然后调试
    从Github上将源码将工程下下来,工程是CMAKE的
    我的编译产物

    VS2022编译库

    直接打开CMakeSetting就可以配置CMAKE
    很方便,不要选TEST,不需要测试相关的源码,当然也可以编成RELEASE的
    在这里插入图片描述

    注意,可能编译会提示有个别文件编码啥不对的,例如我这里是这个文件编码不对
    在这里插入图片描述
    解决的方法是文件,对编码异常的文件另存为
    在这里插入图片描述
    然后弹出的窗口,找到保存下的编码保存
    在这里插入图片描述
    选UTF-8带签名,替换保存
    在这里插入图片描述
    正常来说,编完之后,\out\build\x64-Debug\source 下得到Lib和DLL
    在这里插入图片描述
    头文件在\include下Xlnt文件夹下全部内容

    VS2022编译DEMO

    新建一个空白的工程
    目录结构如下,lib下放编译好的lib文件,x64是输出的位置,把测试用的xlsx放进去
    在这里插入图片描述

    VC++目录界面
    在这里插入图片描述
    链接器设置界面
    在这里插入图片描述

    测试的代码

    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    std::string UTF8_To_string(const std::string& str)
    {
    	int nwLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
    
    	wchar_t* pwBuf = new wchar_t[nwLen + 1];//一定要加1,不然会出现尾巴
    	memset(pwBuf, 0, nwLen * 2 + 2);
    
    	MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), pwBuf, nwLen);
    
    	int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
    
    	char* pBuf = new char[nLen + 1];
    	memset(pBuf, 0, nLen + 1);
    
    	WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
    
    	std::string retStr = pBuf;
    
    	delete[]pBuf;
    	delete[]pwBuf;
    
    	pBuf = NULL;
    	pwBuf = NULL;
    
    	return retStr;
    }
    
    
    
    int main()
    {
    	xlnt::workbook wb;
    	wb.load("test.xlsx");
    	auto ws = wb.active_sheet();
    	std::clog << "读取测试表格" << std::endl;
    	for (auto row : ws.rows(false))
    	{
    		for (auto cell : row)
    		{
    			//std::clog << cell.to_string() << std::endl;
    			string str1 = cell.to_string();
    			string str2 = UTF8_To_string(str1);
    			std::cout << str2 << "\t|";
    		}
    		std::cout << "\r\n";
    	}
    	std::clog << "读取完毕" << std::endl;
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    测试的表格如下
    在这里插入图片描述
    运行的效果是这样的
    在这里插入图片描述
    注意,脱离调试环境运行的时候,需要把程序和DLL放在一起,如果在VS里调试可以不用。

    GCC编译库

    这里我用的是TDM-GCC,目前我下到的版本是gcc.exe (tdm64-1) 10.3.0
    在这里插入图片描述

    安装CMAKE,版本3.25.0-rc4
    安装VSCODE,安装好CMAKE的插件,按照提示选好安装的GCC编译器,CMAKE应该就正常配置了
    在下面可以配置CMake的输出类型和编译器
    在这里插入图片描述
    注意使用GCC编译Xlnt库,需要ninja,下载之后,把它可以放到安装GCC的bin目录下
    关闭测试的代码,打开静态库
    在这里插入图片描述
    也是一样,万一有啥文件编码不正确的情况,请转换成UTF-8
    输出的文件也是看\out\build\x64-Debug\source,得到.a文件
    在这里插入图片描述

    GCC编译DEMO

    VSCODE新建一个工程文件夹,目录结构如下,lib放.a文件,src放源文件,include放相关头文件
    在这里插入图片描述
    .VSCode\c_cpp_properties.json文件

    {
        "configurations": [
            {
                "name": "Win32",
                "includePath": [
                    "${workspaceFolder}/**",
                    "${workspaceFolder}/include/**",
                    "${workspaceFolder}/include/xlnt/**",
                    "${workspaceFolder}/include/xlnt/packaging/**",
                    "${workspaceFolder}/include/xlnt/styles/**",
                    "${workspaceFolder}/include/xlnt/cell/**",
                    "${workspaceFolder}/include/xlnt/drawing/**",
                    "${workspaceFolder}/include/xlnt/utils/**",
                    "${workspaceFolder}/include/xlnt/workbook/**",
                    "${workspaceFolder}/include/xlnt/worksheet/**"
    
                ],
                "defines": [
                    "_DEBUG",
                    "UNICODE",
                    "_UNICODE"
                ],
                "windowsSdkVersion": "10.0.19041.0",
                "compilerPath": "C:/TDM-GCC-64/bin/g++.exe",
                "cStandard": "c11",
                "cppStandard": "c++11",
                "intelliSenseMode": "windows-gcc-x64",
                "configurationProvider": "ms-vscode.cmake-tools"
            }
        ],
        "version": 4
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    .VSCode\launch.json

    {
        "version": "0.2.0",  
        "configurations": [  
        {
            "name": "(gdb) 启动",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/main.exe",
            "args": [],
            "stopAtEntry": true,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\TDM-GCC-64\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description":  "将反汇编风格设置为 Intel",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": true
                }
            ]
        },
            {  
                "name": "(gdb) Launch", // 配置名称,将会在启动配置的下拉菜单中显示
                "type": "cppdbg",       // 配置类型,这里只能为cppdbg
                "request": "launch",    // 请求配置类型,可以为launch(启动)或attach(附加)  
                "program": "${workspaceFolder}/${fileBasenameNoExtension}.exe",// 将要进行调试的程序的路径  
                "args": [],             // 程序调试时传递给程序的命令行参数,一般设为空即可  
                "stopAtEntry": false,   // 设为true时程序将暂停在程序入口处,一般设置为false  
                "cwd": "${workspaceFolder}", // 调试程序时的工作目录,一般为${workspaceFolder}即代码所在目录  
                "environment": [],  
                "externalConsole": true, // 调试时是否显示控制台窗口,一般设置为true显示控制台  
                "MIMode": "gdb",  
                "miDebuggerPath": "C:\\TDM-GCC-64\\bin\\gdb.exe", // miDebugger的路径,注意这里要与MinGw的路径对应  
                "preLaunchTask": "g++", // 调试会话开始前执行的任务,一般为编译程序,c++为g++, c为gcc  
                "setupCommands": [  
                    {   
                "description": "Enable pretty-printing for gdb",  
                        "text": "-enable-pretty-printing",  
                        "ignoreFailures": true  
                    }  
                ]  
            }  
        ]  
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    .VSCode\settings.json

    {
        "files.associations": {
            "new": "cpp",
            "atomic": "cpp",
            "string_view": "cpp",
            "iostream": "cpp",
            "array": "cpp",
            "bit": "cpp",
            "*.tcc": "cpp",
            "cctype": "cpp",
            "clocale": "cpp",
            "cmath": "cpp",
            "compare": "cpp",
            "concepts": "cpp",
            "cstdarg": "cpp",
            "cstddef": "cpp",
            "cstdint": "cpp",
            "cstdio": "cpp",
            "cstdlib": "cpp",
            "cwchar": "cpp",
            "cwctype": "cpp",
            "deque": "cpp",
            "map": "cpp",
            "unordered_map": "cpp",
            "vector": "cpp",
            "exception": "cpp",
            "algorithm": "cpp",
            "functional": "cpp",
            "iterator": "cpp",
            "memory": "cpp",
            "memory_resource": "cpp",
            "numeric": "cpp",
            "optional": "cpp",
            "random": "cpp",
            "string": "cpp",
            "system_error": "cpp",
            "tuple": "cpp",
            "type_traits": "cpp",
            "utility": "cpp",
            "initializer_list": "cpp",
            "iosfwd": "cpp",
            "istream": "cpp",
            "limits": "cpp",
            "ostream": "cpp",
            "ranges": "cpp",
            "sstream": "cpp",
            "stdexcept": "cpp",
            "streambuf": "cpp",
            "typeinfo": "cpp"
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    源文件

    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    
    std::string UTF8_To_string(const std::string& str)
    {
    	int nwLen = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
    
    	wchar_t* pwBuf = new wchar_t[nwLen + 1];//一定要加1,不然会出现尾巴
    	memset(pwBuf, 0, nwLen * 2 + 2);
    
    	MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), pwBuf, nwLen);
    
    	int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
    
    	char* pBuf = new char[nLen + 1];
    	memset(pBuf, 0, nLen + 1);
    
    	WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
    
    	std::string retStr = pBuf;
    
    	delete[]pBuf;
    	delete[]pwBuf;
    
    	pBuf = NULL;
    	pwBuf = NULL;
    
    	return retStr;
    }
    
    
    
    int main()
    {
    	xlnt::workbook wb;
    	wb.load("test.xlsx");
    	auto ws = wb.active_sheet();
    	std::clog <<"读取测试表格"<< std::endl;
    	for (auto row : ws.rows(false))
    	{
    		for (auto cell : row)
    		{
    			//std::clog << cell.to_string() << std::endl;
    			string str1 = cell.to_string();
    			string str2 = UTF8_To_string(str1);
    			std::cout << str2 << "\t|";
    		}
    		std::cout << "\r\n";
    	}
    	std::clog << "读取完毕" << std::endl;
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    CMakeLists.txt
    这个可能我写的复杂了,不过可以用

    cmake_minimum_required (VERSION 2.8.12)#规定cmake的最低版本要求
    project(Cmake_test)#项目的名称,不一定和你的文件夹名称一样
    set(CMAKE_CXX_COMPILER "g++")#设置c++编译器
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fexec-charset=UTF-8")
    
    set(SRC_MAIN ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp)
    
    include_directories(${PROJECT_SOURCE_DIR}/include)
    include_directories(${PROJECT_SOURCE_DIR}/include/xlnt)
    include_directories(${PROJECT_SOURCE_DIR}/include/xlnt/packaging)
    include_directories(${PROJECT_SOURCE_DIR}/include/xlnt/styles)
    include_directories(${PROJECT_SOURCE_DIR}/include/xlnt/cell)
    include_directories(${PROJECT_SOURCE_DIR}/include/xlnt/drawing)
    include_directories(${PROJECT_SOURCE_DIR}/include/xlnt/utils)
    include_directories(${PROJECT_SOURCE_DIR}/include/xlnt/workbook)
    include_directories(${PROJECT_SOURCE_DIR}/include/xlnt/worksheet)
    
    
    # 设置第三方库文件路径(这里全部的第三方库都保存在LIB_FILE变量中)
    file(GLOB LIB_FILE ${PROJECT_SOURCE_DIR}/lib/*.a)
    
    
    set(EXECUTABLE_OUTPUT_PATH  ${PROJECT_SOURCE_DIR}/build)#设置可执行文件输出路径
    
    add_executable(main ${SRC_MAIN})
    target_link_libraries(main ${LIB_FILE}) 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    编译运行之后的效果
    在这里插入图片描述

  • 相关阅读:
    基于Lang-Chain(ChatGLM和ChatChat)知识库大语言模型的部署搭建
    python函数嵌套调用的实现
    这次我设计了一款TPS百万级别的分布式、高性能、可扩展的RPC框架
    GFS 分布式文件系统
    【堆排序】十大排序算法之堆排序
    湘南学院2023级成考新生课程学习安排及成绩评定标准
    开始打击了
    TEMU半托管模式引领跨境电商新风尚
    (二十四)数据结构-选择排序
    SwiftData(iOS 17+)如何在数据新建和更新中途出错时恢复如初?
  • 原文地址:https://blog.csdn.net/tpoem/article/details/127807954