Ubuntu环境下基于libxl库文件使用C++实现对表格的操作

news2024/11/20 14:27:03

功能

  • 表格不存在则创建后再进行操作
  • 创建sheet添加新的工作表
  • 在sheet中增加数据
  • 设置单元格样式

相关配置

  • 下载地址:libxl
  • 选择 LibXL for Linux 4.2.0   i386 x64 armhf aarch64

安装配置

  • 1,使用 tar zxvf 文件名.tar.gz 进行文件解压
  • 2,创建 /usr/local/libxl/lib64目录,将libxl\libxl-4.2.0\lib64文件夹下的libxl.so库文件拷贝到刚才创建的目录下
  • 3,创建 /usr/local/include/libxl目录,将libxl\libxl-4.2.0\include_cpp文件夹下的头文件拷贝到刚才创建的目录下

Clion配置

cmake_minimum_required(VERSION 3.23)
project(libxl_test)

set(CMAKE_CXX_STANDARD 11)

# 指定lib目录
link_directories(/usr/local/libxl/lib64)

# 指定头文件搜索策略
include_directories(/usr/local/include/libxl)

add_executable(libxl_test main.cpp)

target_link_libraries(${PROJECT_NAME}  xl z)

# g++ -o ExcelOutputProgram ExcelOutputProgram.cpp -lxl -lz

代码

#include <iostream>
#include <ctime>
#include <chrono>
#include <fstream>
#include <libxl/libxl.h>

#define filename "/home/chy-cpabe/CLionProjects/libxl_test/output.xlsx"

bool fileExists(const std::string& excel_file) {
    std::ifstream file(excel_file);
    return file.good();  // 如果文件存在,file.good() 返回 true
}

/**
 * @brief 填写表格内容
 *
 * @param USBKey_info                      Book handle
 * @param sheet                           sheet handle
 * @param DEVINFO_SerialNumber             USBKey序列号
 * @param Signing_Certificate_SerialNumber 签名证书序列号
 * @return 0:成功;-1:失败
 */
int write_excel_content(libxl::Book *USBKey_info,libxl::Sheet *sheet,
                        std::string DEVINFO_SerialNumber,
                        std::string Signing_Certificate_SerialNumber)
{
    // 插入相关字段信息
    int nextRowIndex = sheet->lastRow();// 确定下一个可用的行索引
    sheet->writeStr(nextRowIndex, 0, DEVINFO_SerialNumber.c_str());
    sheet->writeStr(nextRowIndex, 1,Signing_Certificate_SerialNumber.c_str());

    // 获取当前系统时间
    auto now = std::chrono::system_clock::now();
    // 将系统时间转化为 time_t 样式
    std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
    // 将time_t转化为tm结构体
    std::tm *localTime = std::localtime(&currentTime);

    // 提取年月日等时间信息
    int year = localTime->tm_year + 1900;  // Years since 1900
    int month = localTime->tm_mon + 1;     // Months start from 0
    int day = localTime->tm_mday;
    int hour = localTime->tm_hour;
    int minute = localTime->tm_min;

    // 设置格式 (每列列宽30并居中显示) 并填充数据
    libxl::Format* format2 = USBKey_info->addFormat();
    format2->setNumFormat(libxl::NUMFORMAT_CUSTOM_MDYYYY_HMM);
    format2->setAlignH(libxl::ALIGNH_CENTER);
    sheet->writeNum(nextRowIndex, 2, USBKey_info->datePack(year,month,day,hour,minute),format2);

}

/**
 * @brief 填写Excel表格
 *
 * @param increase_sheet                         是否增加工作表
 * @param sheetName_new 如果increase_sheet为true,接收工作表的名字
 * @param DEVINFO_SerialNumber                    USBKey序列号
 * @param Signing_Certificate_SerialNumber       签名证书序列号
 * @return 0:成功;-1:失败
 */
int write_excel(bool increase_sheet,std::string sheetName_new,
                std::string DEVINFO_SerialNumber,
                std::string Signing_Certificate_SerialNumber){
    libxl::Book *USBKey_info = xlCreateXMLBook();
    //Excel文件是否存在
    if (!fileExists(filename)) {
        //  创建Excel 文件
        if (USBKey_info->save(filename)) {
            std::cout << "excel表格创建成功!" << std::endl;
        } else {
            std::cout << "excel表格创建失败!" << std::endl;
        }
    }

    //创建表格
    USBKey_info->load(filename);
    //增加sheet
    if (increase_sheet == true){
        // 添加新的工作表并命名
        libxl::Sheet *sheet = USBKey_info->addSheet(sheetName_new.c_str());
        if (sheet) {
            //表格样式处理 (每列列宽30并居中显示)
            libxl::Format* centerAlign = USBKey_info->addFormat();
            centerAlign->setAlignH(libxl::ALIGNH_CENTER);
            sheet->setCol(0, 2, 30, centerAlign);

            // 创建工作表的标题
            sheet->writeStr(1, 0, "DEVINFO SerialNumber");
            sheet->writeStr(1, 1, "Signing Certificate SerialNumber");
            sheet->writeStr(1, 2, "Date");

            // 插入相关字段信息
            write_excel_content(USBKey_info, sheet,DEVINFO_SerialNumber,
                                Signing_Certificate_SerialNumber);
        } else{
            std::cerr << "新增 使用用户指定名称创建sheet的索引失败!" << std::endl;
            return false;
        }
    }else{
        //利旧 获取最后一个sheet的索引
        int sheetCount = USBKey_info->sheetCount()-1;
        libxl::Sheet *sheet = USBKey_info->getSheet(sheetCount);
        if (sheet)
        {
            // 插入相关字段信息
            write_excel_content(USBKey_info, sheet,DEVINFO_SerialNumber,
                                Signing_Certificate_SerialNumber);
        } else{
            std::cerr << "利旧 获取最后一个sheet的索引失败!" << std::endl;
            return false;
        }

    }

    // 保存 Excel 文件
    if (USBKey_info->save(filename)) {
        std::cout << "Excel 文件成功保存" << std::endl;
    } else {
        std::cout << "Excel 文件保存失败" << std::endl;
    }

    // 释放资源
    USBKey_info->release();
    return 0;
}

int main() {
    printf("请输入要创建的工作表名称:\n");
    std::string sheetName; // 用户输入的工作表名称
    std::cin >> sheetName; // 接收用户输入的工作表名称

    std::string DEVINFO_SerialNumber{"00FF4821104E2607"};
    std::string Signing_Certificate_SerialNumber{"4495"};

    //测试1: 文件不存在新建,强制删除文件即可
    write_excel(true,sheetName,DEVINFO_SerialNumber,
                Signing_Certificate_SerialNumber);
    //测试2: 文件存在
        //sheet新建
    write_excel(true,"new1",DEVINFO_SerialNumber,
                Signing_Certificate_SerialNumber);
        //sheet追加
    write_excel(false,"new",DEVINFO_SerialNumber,
                Signing_Certificate_SerialNumber);
    return 0;
}

结果展示

注意

  •  sheet新建需要保证每个sheet的name是不一样的,重名会出错
    //测试2: 文件存在
        //sheet新建
    write_excel(true,"new1",DEVINFO_SerialNumber,
                Signing_Certificate_SerialNumber);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1232855.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【开源】基于Vue.js的森林火灾预警系统的设计和实现

项目编号&#xff1a; S 019 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S019&#xff0c;文末获取源码。} 项目编号&#xff1a;S019&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 系统基础模块2.3 烟…

【Linux】Linux的常用基本指令

Linux常用基本指令 Linux指令的历史背景前言说明一、 ls 列出文件中的所有内容常用选项 二、pwd 显示当前所在目录进程三、cd 将当前工作目录改变到指定的目录下常用样例 四、touch 1. 更改文档或目录的日期时间 2. 新建一个不存在的文件常用选项 四、mkdir 1. 更改文档或目录的…

队列OJ--循环队列

目录 题目链接&#xff1a;622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09;​​​​​ 题解&#xff1a; ​编辑 代码实现&#xff1a; 完整代码&#xff1a; 题目链接&#xff1a;622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09;​​​​​ 题解&#x…

html页面直接使用elementui Plus时间线 + vue3

直接上效果图 案例源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"../js/vue3.3.8/vue.global.js"></script><link rel"styles…

全国见!飞桨星河社区五周年,邀你共赴大模型盛宴!

自2018年对外发布以来&#xff0c;飞桨星河社区已汇集660万AI开发者。感谢大家一路见证了飞桨星河社区的成长&#xff0c; 也很荣幸飞桨星河社区陪伴了大家的AI开发旅程。 在这个大模型时代&#xff0c; 飞桨星河社区期待可以帮助开发者们实现自我价值&#xff0c; 获得更多成长…

Androidstudio中build.gradle classpath如何添加

Androidstudio中build.gradle classpath如何添加 build.gradle classpath如何添加 build.gradle classpath如何添加 升级as之后&#xff0c;gradle版本也升级了&#xff0c;导致project的build.gradle中的写法也不一样了。 buildscript {repositories {google()mavenCentral(…

A*寻路算法

广度优先算法搜索以广度做为优先级进行搜索。 从起点开始&#xff0c;首先遍历起点周围邻近的点&#xff0c;然后再遍历已经遍历过的点邻近的点&#xff0c;逐步的向外扩散&#xff0c;直到找到终点。 这种算法就像洪水&#xff08;Flood fill&#xff09;一样向外扩张。直至…

CRM系统的销售预测是什么?怎么做?

简单来说&#xff0c;销售预测可以通过销售关键信息为团队预测收入&#xff0c;分配目标。CRM中的销售预测可以帮助企业制定合理的销售目标和策略&#xff0c;并通过实时数据发现瓶颈所在&#xff0c;提高团队绩效。下面说说CRM中销售预测是什么&#xff1f;如何销售预测&#…

广度优先算法(BFS)

广度优先算法&#xff08;Breadth-First Search&#xff09;是在图和树领域的搜索方法&#xff0c;其核心思想是从一个起始点开始&#xff0c;访问其所有的临近节点&#xff0c;然后再按照相同的方式访问这些临近节点的节点&#xff0c;这种访问方式类似涟漪泛起&#xff0c;一…

[汇编实操]DOSBox工具安装——Ubuntu18.04系统

一、下载&安装 sudo apt install -y dosbox 二、启动 dosbox 三、C盘挂载 将上述文件下载放在任意路径&#xff0c;将DEBUG目录映射为虚拟C盘 MASM.EXE 是用来编译的&#xff0c;LINK.EXE 用来链接&#xff0c;这俩是必须的。 执行如下命令&#xff1a; mount c /m…

基于Java封装继承多态实现的一个简单图书系统

首先我们大概了解下图书系统的需求 1.要有两种身份 管理员和普通用户。普通用户和管理员分别对应的功能不一样&#xff0c;需要分开实现 2. 图书系统肯定要有图书&#xff0c;和存放图书的地方&#xff0c;存放就用数组来实现 3.实现对应用户的功能 接下来我们第一步&#xf…

react重要知识点(面经)

react重要知识点&#xff08;面经&#xff09; react生命周期classhooks reduxredux 核心概念redux 计数器案例 react页面加载卡顿使用懒加载异步加载JavaScript压缩和缓存静态资源使用React.memo() PubSub使用方式1.1 react导入库1.2 react 页面引入pubsubjs1.3 pubsubjs使用2…

企业要满足什么条件才能实施CRM系统?

CRM的作用相信大家也所有了解&#xff0c;但并不是所有的企业都适合实施CRM。或者说&#xff0c;大部分企业实施CRM并不会100%的成功。那么&#xff0c;企业实施CRM的条件是什么&#xff1f;下面我们就来说一说。 1、业务规模 如果您的客户数量较少&#xff0c;没有复杂的客户…

数据中心走向绿色低碳,液冷存储舍我其谁

引言&#xff1a;没有最冷&#xff0c;只有更冷&#xff0c;绿色低碳早已成为行业关键词。 【全球存储观察 &#xff5c; 科技热点关注】 每一次存储行业的创新&#xff0c;其根源离不开行业端的用户需求驱动。 近些年从数据中心建设的整体发展情况来看&#xff0c;从风冷到…

隧道ip网络广播系统

隧道ip网络广播系统 隧道ip网络广播系统的优势有那些&#xff1f; 节省人力及维护成本&#xff1a;隧道ip网络广播系统可以自动播放节目&#xff0c;无需人工操作&#xff0c;节省了人力成本。定时广播&#xff0c;分区广播&#xff0c;全区广播&#xff0c;方便管理和简易化…

钩子函数-hook

钩子函数-hook hook 的作用 利用钩子函数可以在所有测试用例执行前做一些预置操作&#xff08;如&#xff1a;准被测试数据、测试环境&#xff09; 或者在测试结束后做一些后置操作&#xff08;如&#xff1a;清理测试数据&#xff09; 钩子函数在其它框架中也有&#xff0…

在线客服系统源码 聊天记录实时保存 附带完整的搭建教程

在线客服系统是一个企业网站进行网络营销的最重要的工具。企业进行网络宣传后&#xff0c;会有很多访客进入到网站&#xff0c;这时候网站就需要有在线客服人员进行接待&#xff0c;及时的与访客进行沟通&#xff0c;才能留住访客&#xff0c;变流量为销量。 在线客服系统可以…

Vue框架学习笔记——指令语法:v-bind动态绑定属性、data的层级结构

文章目录 指令语法v-bind&#xff0c;增加标签内属性动态绑定方式 data的层级结构 指令语法 在标签中想让属性动态变化的时候&#xff0c;不能使用插值语法。 插值语法一般用于标签体中&#xff0c;当针对标签的里面的时候&#xff0c;例如标签属性&#xff0c;就可以使用指令…

捷报连连!怿星科技荣获北京市科学技术进步奖一等奖

近期&#xff0c;北京市科学技术委员会、中关村科技园区管理委员会揭晓了2022年北京市科学技术奖的获奖名单。其中&#xff0c;由清华大学牵头、怿星科技参与开发的《电动汽车底盘运动控制与能量管理关键技术及应用》项目荣获“北京市科学技术进步奖一等奖”。 作为北京市政府设…

销售团队可以借助CRM系统做什么?

销售主管都想有一支效率高、质量高的销售团队&#xff0c;无论对于初创企业还是大型企业销售团队都是企业盈利的主力部门&#xff0c;直接为企业带了业绩。如何提升销售团队水平&#xff1f;离不开CRM系统的辅助&#xff0c;CRM软件能为销售团队提供哪些支持&#xff1f;下面我…