决定使用 CPP 库处理 xls 问题
This commit is contained in:
15
go/go.mod
15
go/go.mod
@@ -1,15 +0,0 @@
|
||||
module xlsxUtils
|
||||
|
||||
go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/richardlehane/mscfb v1.0.6 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.6 // indirect
|
||||
github.com/tiendc/go-deepcopy v1.7.2 // indirect
|
||||
github.com/xuri/efp v0.0.1 // indirect
|
||||
github.com/xuri/excelize/v2 v2.10.1 // indirect
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
|
||||
golang.org/x/crypto v0.48.0 // indirect
|
||||
golang.org/x/net v0.50.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
)
|
||||
18
go/go.sum
18
go/go.sum
@@ -1,18 +0,0 @@
|
||||
github.com/richardlehane/mscfb v1.0.6 h1:eN3bvvZCp00bs7Zf52bxNwAx5lJDBK1tCuH19qq5aC8=
|
||||
github.com/richardlehane/mscfb v1.0.6/go.mod h1:pe0+IUIc0AHh0+teNzBlJCtSyZdFOGgV4ZK9bsoV+Jo=
|
||||
github.com/richardlehane/msoleps v1.0.6 h1:9BvkpjvD+iUBalUY4esMwv6uBkfOip/Lzvd93jvR9gg=
|
||||
github.com/richardlehane/msoleps v1.0.6/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/tiendc/go-deepcopy v1.7.2 h1:Ut2yYR7W9tWjTQitganoIue4UGxZwCcJy3orjrrIj44=
|
||||
github.com/tiendc/go-deepcopy v1.7.2/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ=
|
||||
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
|
||||
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/excelize/v2 v2.10.1 h1:V62UlqopMqha3kOpnlHy2CcRVw1V8E63jFoWUmMzxN0=
|
||||
github.com/xuri/excelize/v2 v2.10.1/go.mod h1:iG5tARpgaEeIhTqt3/fgXCGoBRt4hNXgCp3tfXKoOIc=
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE=
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
@@ -1 +0,0 @@
|
||||
package main
|
||||
24
lib_cpp/CMakeLists.txt
Normal file
24
lib_cpp/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(xlsx_reader VERSION 1.0.0 LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
add_subdirectory(third_party/OpenXLSX)
|
||||
|
||||
set(OPENXLSX_STATIC ON CACHE BOOL "Build OpenXLSX as static library")
|
||||
FetchContent_MakeAvailable(OpenXLSX)
|
||||
|
||||
add_library(xlsx_reader SHARED src/xlsx_reader.cpp)
|
||||
|
||||
target_include_directories(xlsx_reader PUBLIC include)
|
||||
|
||||
target_link_libraries(xlsx_reader PRIVATE OpenXLSX::OpenXLSX)
|
||||
|
||||
target_compile_definitions(xlsx_reader PRIVATE XLSX_BUILD_SHARED)
|
||||
28
lib_cpp/include/xlsx_reader.h
Normal file
28
lib_cpp/include/xlsx_reader.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef XLSX_READER_H
|
||||
#define XLSX_READER_H
|
||||
|
||||
#if defined(_WIN32)
|
||||
#if defined(XLSX_BUILD_SHARED)
|
||||
#define XLSX_API __declspec(dllexport)
|
||||
#else
|
||||
#define XLSX_API __declspec(dllimport)
|
||||
#endif
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define XLSX_API __attribute__((visibility("default")))
|
||||
#else
|
||||
#define XLSX_API
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
XLSX_API char* xlsx_read_first_sheet(const char* filepath);
|
||||
|
||||
XLSX_API void xlsx_free_string(char* str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
96
lib_cpp/src/xlsx_reader.cpp
Normal file
96
lib_cpp/src/xlsx_reader.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "xlsx_reader.h"
|
||||
|
||||
#include <OpenXLSX/OpenXLSX.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
static std::string jsonEscape(const std::string& s) {
|
||||
std::string out;
|
||||
out.reserve(s.size() + 2);
|
||||
for (char c : s) {
|
||||
switch (c) {
|
||||
case '"': out += "\\\""; break;
|
||||
case '\\': out += "\\\\"; break;
|
||||
case '\n': out += "\\n"; break;
|
||||
case '\t': out += "\\t"; break;
|
||||
case '\r': out += "\\r"; break;
|
||||
default:
|
||||
if (static_cast<unsigned char>(c) < 0x20) {
|
||||
char buf[8];
|
||||
std::snprintf(buf, sizeof(buf), "\\u%04x",
|
||||
static_cast<unsigned char>(c));
|
||||
out += buf;
|
||||
} else {
|
||||
out += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::string cellAsString(const OpenXLSX::XLCell& cell) {
|
||||
using namespace OpenXLSX;
|
||||
auto& val = cell.value();
|
||||
switch (val.type()) {
|
||||
case XLValueType::Integer:
|
||||
return std::to_string(val.get<int64_t>());
|
||||
case XLValueType::Float:
|
||||
return std::to_string(val.get<double>());
|
||||
case XLValueType::String:
|
||||
return val.get<std::string>();
|
||||
case XLValueType::Boolean:
|
||||
return val.get<bool>() ? "true" : "false";
|
||||
case XLValueType::Empty:
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" XLSX_API char* xlsx_read_first_sheet(const char* filepath) {
|
||||
if (!filepath) return nullptr;
|
||||
|
||||
try {
|
||||
OpenXLSX::XLDocument doc;
|
||||
doc.open(filepath);
|
||||
|
||||
auto wks = doc.workbook().worksheet(1);
|
||||
|
||||
std::string json;
|
||||
json += '[';
|
||||
|
||||
bool firstRow = true;
|
||||
for (auto& row : wks.rows()) {
|
||||
if (!firstRow) json += ',';
|
||||
json += '[';
|
||||
|
||||
bool firstCell = true;
|
||||
for (auto& cell : row.cells()) {
|
||||
if (!firstCell) json += ',';
|
||||
json += '"';
|
||||
json += jsonEscape(cellAsString(cell));
|
||||
json += '"';
|
||||
firstCell = false;
|
||||
}
|
||||
|
||||
json += ']';
|
||||
firstRow = false;
|
||||
}
|
||||
|
||||
json += ']';
|
||||
doc.close();
|
||||
|
||||
char* result = static_cast<char*>(std::malloc(json.size() + 1));
|
||||
if (result) {
|
||||
std::memcpy(result, json.c_str(), json.size() + 1);
|
||||
}
|
||||
return result;
|
||||
} catch (const std::exception&) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" XLSX_API void xlsx_free_string(char* str) {
|
||||
std::free(str);
|
||||
}
|
||||
Reference in New Issue
Block a user