poi-tl之图表操作(基于模板)

news2024/9/25 3:24:45

poi-tl(poi template language)是Word模板引擎,使用Word模板和数据创建很棒的Word文档。
核心思想是在模板中放一个占位符,在代码中替换该占位符即可。
poi官网地址 点这里

基础工作

maven配置

<dependency>
    <groupId>com.deepoove</groupId>
    <artifactId>poi-tl</artifactId>
    <version>1.10.0</version> <!-- 替换为你想要使用的特定版本 -->
</dependency>

chart

chart分为三种类型,分别是单系列、多系列及组合。

  • 单系列图表指的是饼图(3D饼图)、圆环图等。
  • 多系列图表指的是条形图(3D条形图)、柱形图(3D柱形图)、面积图(3D面积图)、折线图(3D折线图)、雷达图、散点图等。
  • 组合图表指的是由多系列图表(柱形图、折线图、面积图)组合而成的图表。

单系列-饼图

  1. 代码如下
public static void main(String[] args) throws IOException {
      Map<String, Object> map = new HashMap<>();
      ChartSingleSeriesRenderData demo1 = Charts.ofPie3D("", new String[]{"第一季度", "第二季度", "第三季度", "第四季度"})
              .series("", new Number[]{0.3, 0.3, 0.2, 0.2})
              .create();
      map.put("demo1", demo1);
      XWPFTemplate.compile("C:\\Users\\huahua\\Desktop\\2.doc").render(map).writeToFile("C:\\Users\\huahua\\Desktop\\demo_output.doc");
}
  1. word模板

插入图表模板后,在图表空白区域右键选择设置图表区域格式->右侧属性选择文本选项->文本框->可选文字
,在标题中输入{{demo1}},其中{{}}为替换标签,必须满足该格式,demo作为属性值,可以修改,注意和代码中map.put("demo1", demo1);设置的键保持一致即可
在这里插入图片描述

此处模板我使用的是wps,wps和office不同,office直接右键查看可选文字即可,如下图所示
在这里插入图片描述

导出结果如下
在这里插入图片描述

多系列-柱状图

    public static void main(String[] args) throws IOException {
        Map<String, Object> map = new HashMap<>();
      
        ChartMultiSeriesRenderData demo2 = Charts.ofBar("", new String[]{"销售量"})
                .addSeries("第一季度", new Number[]{100})
                .addSeries("第二季度", new Number[]{200})
                .addSeries("第三季度", new Number[]{500})
                .addSeries("第四季度", new Number[]{1000})
                .create();
        map.put("demo2", demo2);
        XWPFTemplate.compile("C:\\Users\\huahua\\Desktop\\2.doc").render(map).writeToFile("C:\\Users\\huahua\\Desktop\\demo_output.doc");
    }

生成的图表如下
在这里插入图片描述

组合系列-柱状折线组合图

Map<String, Object> map = new HashMap<>();
ChartMultiSeriesRenderData demo3 = Charts.ofComboSeries("MyChart", new String[] { "中文", "English" })
        .addBarSeries("countries", new Double[] { 15.0, 6.0 })
        .addBarSeries("speakers", new Double[] { 223.0, 119.0 })
        .addBarSeries("NewBar", new Double[] { 223.0, 119.0 })
        .addLineSeries("youngs", new Double[] { 323.0, 89.0 })
        .addLineSeries("NewLine", new Double[] { 123.0, 59.0 }).create();
map.put("demo3", demo3);
XWPFTemplate.compile("C:\\Users\\huahua\\Desktop\\2.doc").render(map).writeToFile("C:\\Users\\huahua\\Desktop\\demo_output.doc");

在这里插入图片描述

小结

不同的chart配置都大同小异,基本都没什么难度,简单了解下就能上手

table

表格分为静态表格和动态表格,

静态表格

当表格的需求比较简单时,可以通过简单的模板替换及列表循环填充表格数据

模板替换

行循环

列循环

动态表格

当需求中的表格更加复杂的时候,我们完全可以设计好那些固定的部分,将需要动态渲染的部分单元格交给自定义模板渲染策略。poi-tl提供了抽象表格策略 DynamicTableRenderPolicy 来实现这样的功能。

以官网模板为例
在这里插入图片描述

策略类

import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.policy.TableRenderPolicy;
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

import java.util.List;

public class DetailTablePolicy extends DynamicTableRenderPolicy {
    // 货品填充数据所在行数
    int goodsStartRow = 2;
    // 人工费填充数据所在行数
    int laborsStartRow = 5;

    @Override
    public void render(XWPFTable table, Object data) throws Exception {
        if (null == data) return;
        DetailData detailData = (DetailData) data;

        // 人工费
        List<RowRenderData> labors = detailData.getLabors();
        if (null != labors) {
            table.removeRow(laborsStartRow);
            // 循环插入行
            for (int i = 0; i < labors.size(); i++) {
                XWPFTableRow insertNewTableRow = table.insertNewTableRow(laborsStartRow);
                for (int j = 0; j < 7; j++) insertNewTableRow.createCell();

                // 横合并单元格
                TableTools.mergeCellsHorizonal(table, laborsStartRow, 0, 3);
                // 单行渲染
                TableRenderPolicy.Helper.renderRow(table.getRow(laborsStartRow), labors.get(i));
            }
        }

        // 货物
        List<RowRenderData> goods = detailData.getGoods();
        if (null != goods) {
            table.removeRow(goodsStartRow);
            for (int i = 0; i < goods.size(); i++) {
                XWPFTableRow insertNewTableRow = table.insertNewTableRow(goodsStartRow);
                for (int j = 0; j < 7; j++) insertNewTableRow.createCell();
                TableRenderPolicy.Helper.renderRow(table.getRow(goodsStartRow), goods.get(i));
            }
        }
    }
}

实体类对象

PaymentData.java
import com.deepoove.poi.expression.Name;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import office.DetailData;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PaymentData {

    @Name("detail_table")
    private DetailData detailTable;

}
DetailData.java
import com.deepoove.poi.data.RowRenderData;
import lombok.Data;

import java.util.List;

@Data
public class DetailData {
    // 货品数据
    private List<RowRenderData> goods;

    // 人工费数据
    private List<RowRenderData> labors;
}

单元测试类

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.Rows;
import excel.DetailTablePolicy;
import org.junit.jupiter.api.BeforeEach;

import java.util.Arrays;
import java.util.List;

public class Test {

    String resource = "C:\\Users\\huahua\\Desktop\\demo\\table.docx";
    PaymentData datas = new PaymentData();

    @BeforeEach
    public void init() {
        datas.setTotal("总共:7200");
        DetailData detailTable = new DetailData();
        RowRenderData rowRenderData = Rows.of("4", "墙纸", "书房+卧室", "1500", "/", "400", "1600").center().create();
        List<RowRenderData> goods = Arrays.asList(rowRenderData, rowRenderData, rowRenderData);

        RowRenderData labor = Rows.of("油漆工", "2", "200", "400").center().create();
        List<RowRenderData> labors = Arrays.asList(labor, labor, labor, labor);
        detailTable.setGoods(goods);
        detailTable.setLabors(labors);
        datas.setDetailTable(detailTable);
    }

    @org.junit.jupiter.api.Test
    public void testPaymentExample() throws Exception {
        Configure config = Configure.builder().bind("detail_table", new DetailTablePolicy()).build();
        XWPFTemplate template = XWPFTemplate.compile(resource, config).render(datas);
        template.writeToFile("C:\\Users\\huahua\\Desktop\\demo\\table_output.docx");
    }
}

扩展

表格数据绑定

这里有个特别需要注意的地方,就是@Name("detail_table"),这个对象的值一定要和模板中的保持一致,否则在表格对象绑定的时候无法绑定到数据,从 XWPFTemplate template = XWPFTemplate.compile(resource, config).render(datas);绑定数据的时候传递到自定义测策略中的时候,数据会丢失,底层源码如下

  void visit(ElementTemplate eleTemplate) {
      RenderPolicy policy = eleTemplate.findPolicy(this.template.getConfig());
      Objects.requireNonNull(policy, "Cannot find render policy: [" + eleTemplate.getTagName() + "]");
      if (!(policy instanceof DocxRenderPolicy)) {
          logger.info("Start render Template {}, Sign:{}, policy:{}", new Object[]{eleTemplate, eleTemplate.getSign(), ClassUtils.getShortClassName(policy.getClass())});
          policy.render(eleTemplate, this.renderDataCompute.compute(eleTemplate.getTagName()), this.template);
      }
  }

this.renderDataCompute.compute(eleTemplate.getTagName(),其中renderDataCompute是我们单元测试类中传递的datas数据,eleTemplate.getTagName()是word模板中的{{detail_table}},从我们传递的数据中获取detail_table这个属性,并传递给render方法,这就是为什么如果属性名不匹配,render方法取不到值的原因。
至于total属性为什么不需要,后续再补充

单元格合并

横向单元格合并在行渲染的时候执行,纵向单元格合并在行渲染后执行,下面是一个行渲染的例子,每5行的第一列合并为一列

    public void render(XWPFTable table, Object data) throws Exception {
        if (null == data) return;
        List<DetailData2> dataList = (List<DetailData2>) data;
        if (dataList.size() == 0) return;

        //设置表格属性
        setTableType(table);
        // 循环插入行, 有多少条数据就有多少行
        //插入的时候是倒序插入的,所以循环遍历的时候倒序遍历
        for (int i = dataList.size()-1; i >=0; i--) {
            XWPFTableRow insertNewTableRow = table.insertNewTableRow(goodsStartRow);
            //创建单元格,即一行包含几列
            for (int j = 0; j < 11; j++) insertNewTableRow.createCell();
            // 单行渲染
            RowRenderData rowRenderData = this.getCellList(dataList.get(i));
            TableRenderPolicy.Helper.renderRow(table.getRow(goodsStartRow), rowRenderData);
        }

        //合并单元格
        int start = 3;
        for (int i = 0; i < dataList.size()/5; i++) {
        	//合并table对象从start-start+4行的第0列
            TableTools.mergeCellsVertically(table, 0, start, start+4);
            start += 5;
        }

    }

render方法中,行是从后向前渲染的,所以数据需要从后向前遍历,因为案例的数据都是一样的,所以没按照次做法。

渲染场景

在这里插入图片描述
支持渲染整个表格,渲染行和渲染单元格三种场景,表格暂时没用到,先不介绍。

渲染行

渲染行即模板只包含table的表头,下面的行数据需要手动渲染。模板文件可参考动态表格的第一个事例
核心代码如下

		for (int i = dataList.size()-1; i >=0; i--) {
            XWPFTableRow insertNewTableRow = table.insertNewTableRow(goodsStartRow);
            //创建单元格,即一行包含几列
            for (int j = 0; j < 11; j++) insertNewTableRow.createCell();
            // 单行渲染
            RowRenderData rowRenderData = this.getCellList(dataList.get(i));
            TableRenderPolicy.Helper.renderRow(table.getRow(goodsStartRow), rowRenderData);
        }

完整代码如下,其中包含了table及行和单元格样式的设置

package excel;

import com.deepoove.poi.data.*;
import com.deepoove.poi.data.style.*;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.policy.TableRenderPolicy;
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.*;

import java.util.Arrays;
import java.util.List;

public class DetailTablePolicy2 extends DynamicTableRenderPolicy {
    // 货品填充数据所在行数
    int goodsStartRow = 3;

    @Override
    public void render(XWPFTable table, Object data) throws Exception {
        if (null == data) return;
        List<DetailData2> dataList = (List<DetailData2>) data;
        if (dataList.size() == 0) return;

        //设置表格属性
        setTableType(table);
        // 循环插入行, 有多少条数据就有多少行
        //插入的时候是倒序插入的,所以循环遍历的时候倒序遍历
        for (int i = dataList.size()-1; i >=0; i--) {
            XWPFTableRow insertNewTableRow = table.insertNewTableRow(goodsStartRow);
            //创建单元格,即一行包含几列
            for (int j = 0; j < 11; j++) insertNewTableRow.createCell();
            // 单行渲染
            RowRenderData rowRenderData = this.getCellList(dataList.get(i));
            TableRenderPolicy.Helper.renderRow(table.getRow(goodsStartRow), rowRenderData);
        }

        //合并单元格
        int start = 3;
        for (int i = 0; i < dataList.size()/5; i++) {
            TableTools.mergeCellsVertically(table, 0, start, start+4);
            start += 5;
        }

    }

    private void setTableType(XWPFTable table) {
        table.setTableAlignment(TableRowAlign.CENTER);
        table.setRightBorder(XWPFTable.XWPFBorderType.DOUBLE, 1, 0, "898989");
        table.setLeftBorder(XWPFTable.XWPFBorderType.THICK, 1, 0, "898989");
        table.setBottomBorder(XWPFTable.XWPFBorderType.THICK, 1, 0, "898989");
        table.setTopBorder(XWPFTable.XWPFBorderType.THICK, 1, 0, "898989");
        table.setInsideHBorder(XWPFTable.XWPFBorderType.THICK, 1, 0, "898989");
        table.setInsideVBorder(XWPFTable.XWPFBorderType.THICK, 1, 0, "898989");
    }

    public RowRenderData getCellList(DetailData2 detailData2) {
        RowRenderData rowRenderData = new RowRenderData();

        setRowType(rowRenderData);

        rowRenderData.addCell(createCell(detailData2.getName()));
        rowRenderData.addCell(createCell(detailData2.getRange()));
        operateValue(rowRenderData, detailData2.getNo1(),detailData2.getNo2(),detailData2.getNo3(),detailData2.getNo4(),detailData2.getNo5(),
                detailData2.getNo6(),detailData2.getNo7(),detailData2.getNo8(),detailData2.getNo9());
        return rowRenderData;
    }

    private void setRowType(RowRenderData rowRenderData) {
        //行样式
        RowStyle rowStyle = new RowStyle();
        rowRenderData.setRowStyle(rowStyle);

        //文本样式
        ParagraphStyle defaultParaStyle = new ParagraphStyle();
        defaultParaStyle.setAlign(ParagraphAlignment.CENTER);

        //单元格样式
        CellStyle defaultCellStyle = new CellStyle();
        defaultCellStyle.setVertAlign(XWPFTableCell.XWPFVertAlign.CENTER);
        defaultCellStyle.setDefaultParagraphStyle(defaultParaStyle);
        rowStyle.setDefaultCellStyle(defaultCellStyle);



    }

    private CellRenderData createCell(Object text) {
        return Cells.of(String.valueOf(text)).create();
    }

    private void operateValue(RowRenderData rowRenderData, int... values) {
        Arrays.stream(values).mapToObj((value) -> {
            CellRenderData cellRenderData = Cells.of(String.valueOf(value)).create();
            CellStyle cellStyle = new CellStyle();
            if (value > 50 ) {
                //单元格背景色
                cellStyle.setBackgroundColor("FFFF00");
                //文本样式
//                paragraphStyle.setDefaultTextStyle(new Style("FF7D7D"));
            } else if (value > 0) {
                cellStyle.setBackgroundColor("FF7D7D");
            } else {
                cellStyle.setBackgroundColor("92D050");
            }
            cellRenderData.setCellStyle(cellStyle);
            return cellRenderData;
        }).forEach(cellRenderData -> rowRenderData.addCell(cellRenderData));
    }
}
渲染单元格

渲染单元格同比渲染行简单一些,因为模板是完整的,我们只需要像渲染静态表格那样,替换单元格的内容及样式即可。这里为什么不使用静态表格,是因为静态表格只能修改文本及其样式,这里我们需要修改单元格的背景色。

		for (int i = dataList.size()-1; i >=0; i--) {
            int[] values = dataList.get(i);
            XWPFTableRow insertNewTableRow = table.getRow(goodsStartRow);
            // 单行渲染
            for (int j = 2; j < 11; j++) {
                CellRenderData cellRenderData = this.getCell(values[j-2]);
                TableRenderPolicy.Helper.renderCell(insertNewTableRow.getCell(j), cellRenderData, cellRenderData.getCellStyle(), defaultTextStyle);
            }
            goodsStartRow++;
        }

完整代码如下

package excel;

import com.deepoove.poi.data.CellRenderData;
import com.deepoove.poi.data.Cells;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.style.CellStyle;
import com.deepoove.poi.data.style.ParagraphStyle;
import com.deepoove.poi.data.style.RowStyle;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.policy.TableRenderPolicy;
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.*;

import java.util.Arrays;
import java.util.List;

public class DetailTablePolicy3 extends DynamicTableRenderPolicy {
    // 货品填充数据所在行数
    int goodsStartRow = 3;

    @Override
    public void render(XWPFTable table, Object data) throws Exception {
        if (null == data) return;
        List<int[]> dataList = (List<int[]>) data;
        if (dataList.size() == 0) return;


        Style defaultTextStyle = new Style();


        // 循环插入行, 有多少条数据就有多少行
        //插入的时候是倒序插入的,所以循环遍历的时候倒序遍历
        for (int i = dataList.size()-1; i >=0; i--) {
            int[] values = dataList.get(i);
            XWPFTableRow insertNewTableRow = table.getRow(goodsStartRow);
            // 单行渲染
            for (int j = 2; j < 11; j++) {
                CellRenderData cellRenderData = this.getCell(values[j-2]);
                TableRenderPolicy.Helper.renderCell(insertNewTableRow.getCell(j), cellRenderData, cellRenderData.getCellStyle(), defaultTextStyle);
            }
            goodsStartRow++;
        }
    }

    private CellRenderData getCell(int value) {
        CellRenderData cellRenderData = Cells.of(String.valueOf(value)).create();

        CellStyle cellStyle = new CellStyle();
        cellStyle.setVertAlign(XWPFTableCell.XWPFVertAlign.CENTER);
        if (value > 50 ) {
            //单元格背景色
            cellStyle.setBackgroundColor("FFFF00");
        } else if (value > 0) {
            cellStyle.setBackgroundColor("FF7D7D");
        } else {
            cellStyle.setBackgroundColor("92D050");
        }
        cellRenderData.setCellStyle(cellStyle);

        ParagraphStyle defaultParagraphStyle = new ParagraphStyle();
        defaultParagraphStyle.setAlign(ParagraphAlignment.CENTER);
        cellStyle.setDefaultParagraphStyle(defaultParagraphStyle);
        return cellRenderData;
    }
}

模板文件参考如下表格,使用于这种表格行数固定及有几列固定值的场景:
在这里插入图片描述

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

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

相关文章

猫头虎分享2023年12月17日博客之星候选--城市赛道博主文章数据

猫头虎分享2023年12月17日博客之星候选–城市赛道博主文章数据 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开…

云渲染UE4像素流送搭建(winows、ubuntu)

windows/ubuntu20.4下UE4.27.2像素流送 像素流送技术可以将服务器端打包的虚幻引擎应用程序在客户端的浏览器上运行&#xff0c;用户可以通过浏览器操作虚幻引擎应用程序&#xff0c;客户端无需下载虚幻引擎&#xff0c;本文实现两台机器通过物理介质网线实现虚幻引擎应用程序…

给零基础朋友的编程课07 - 代码

给零基础朋友的编程课07-初识色彩、初识变量、案例3讲解_哔哩哔哩_bilibili Code: // // 案例3 // //// -设定画面- // size(1000, 1000); // 设置画面大小 background(7, 119, 132); // 设置背景颜色// - 绘画 - //// 1 绘制垂线 // 设定线条风格 …

医药保健品企业网站搭建的作用是什么

市场中的保健品品牌非常多&#xff0c;很多医院或药店都有售卖&#xff0c;同时也有不少经常消费的人群&#xff0c;但从行业整体趋势来看&#xff0c;目前国内真正信任保健品的人并不算非常多&#xff0c;行业缺少对市场消费人群的教育及行业的相关限制&#xff0c;无论对品牌…

超炫酷的网红游戏主播/带货达人/歌手/人物介绍视频素材PR模板

Premiere网红//游戏主播、带货达人\主唱歌手\DJ晚会派对人物介绍视频素材pr模板下载。 包括&#xff1a; 全高清&#xff08;19201080&#xff09; 4K&#xff0c;&#xff08;38402160&#xff09; 全高清&#xff08;19201080&#xff09; 4K&#xff0c;&#xff08;3840216…

Tailwind CSS 原子化开发初体验

Tailwind CSS 的工作原理是扫描所有 HTML 文件、JavaScript 组件以及任何模板中的 CSS 类&#xff08;class&#xff09;名&#xff0c;然后生成相应的样式代码并写入到一个静态 CSS 文件中。他快速、灵活、可靠&#xff0c;没有运行时负担。再也不用为了取一个 classname 类名…

使用 FFmpeg 清除文件夹下所有 .mp4 文件声音

运行以下命令来清除声音&#xff1a; ffmpeg -i input.mp4 -c copy -an output.mp4这个命令会将 “input.mp4” 替换为你要处理的 .mp4 文件名。它会生成一个新的文件名为 “output.mp4” 的文件&#xff0c;该文件是没有声音的副本。 如果你想要直接替换原始文件&#xff0c;…

文件名修改方法:文件批量重命名,并将扩展字母统一转换为大写

在文件管理中&#xff0c;文件名的修改是一项常见的任务。有时候&#xff0c;可能要将文件名进行批量重命名&#xff0c;或者将所有的扩展名统一转换为大写。那怎么操作会更简单快速些呢&#xff1f;下面将详细讲解云炫文件管理器如何实现这一目标&#xff0c;批量用随机数字重…

MongoDB查询文档

3.5 MongoDB 查询文档 MongoDB 查询文档使用 find() 方法。 find() 方法以非结构化的方式来显示所有文档。find()查询数据的语法格式如下&#xff1a; db.collection.find(query, projection)[.pretty()] query &#xff1a;可选&#xff0c;使用查询操作符指定查询条件 pr…

哪个牌子的台灯对学生的视力好?五款学生备考台灯推荐

护眼台灯在如今市场中销量越来越高&#xff0c;我作为一名电器测评博主&#xff0c;非常支持大家使用护眼台灯来提升日常的照明光线环境&#xff0c;它通过LED灯和专业的护眼技术&#xff0c;可以有效缓解用眼疲劳、帮助放松和舒适照明。但需要注意的是&#xff0c;目前市场中品…

【excel密码】Excel工作表不能复制或移动

为什么excel文件打开之后&#xff0c;工作表里是可以编辑的&#xff0c;但是想要移动工作表或者复制、重命名等操作&#xff0c;这是什么原因&#xff1f;其实这是因为设置了工作簿保护&#xff0c;设置了保护的工作簿无法对整张工作表进行操作。 想要取消这种保护&#xff0c;…

操作系统期末复习知识点二计算与应用

1.理解银行家算法判断死锁的定理并能计算相关的参数。 2.能利用LRU、FIFO算法求缺页率。 3.纯页式管理中&#xff0c;求逻辑地址对应的物理地址&#xff0c;页号、页内地址长度&#xff0c;画出逻辑地址的格式&#xff0c;在引入块表时&#xff0c;求出有效访问时间。 4.可变分…

西门子PLC通过PROFINET协议与多功能电表通讯

西门子PLC通过PROFINET协议与多功能电表通讯 项目要求 西门子S71200PLC需要通过PROFINET协议和多功能电表通讯&#xff0c;读取线电压、相电压、线电流、相电流、有功功率、无功功率等参数。 项目实施 采用网关NET90-PN-MBT&#xff08;以下简称“网关”&#xff09;&#…

【Java】SpringBoot快速整合Kafka

目录 1.什么是Kafka&#xff1f; 主要特点和概念&#xff1a; 主要组成部分&#xff1a; 2.Kafka可以用来做什么&#xff1f; 3.SpringBoot整合Kafka步骤&#xff1a; 1. 添加依赖: 2. 配置 Kafka: 3. 创建 Kafka 生产者: 4. 创建 Kafka 消费者: 5. 发布消息: 6. 使…

探索AIGC时代效能提升新路径,企业快成长AI技术创新论坛广州站圆满闭幕

在广泛数据的不断滋养下&#xff0c;AIGC技术愈发成熟。利用AIGC技术的生成能力辅助进行文案撰写、海报生成、美术设计已成为众多行业的高频需求。如今AIGC技术已走入更新发展的新时期&#xff0c;挖掘能力、探索场景&#xff0c;沉淀更多高效易用的精细化模型&#xff0c;也成…

3D渲染农场什么比较好用 2024渲染农场最新收费实测

随着数字设计领域的进步与发展&#xff0c;对于3D渲染服务的需求日益增加。3D渲染农场这一概念因此变得极为重要&#xff0c;特别是在电影制作、建筑可视化以及产品设计等行业中。现在&#xff0c;让我们深入了解3D渲染农场的定义以及市面上优秀的3D渲染服务提供商。 一、什么是…

Shell脚本应用(四)

一、文本处理器 1、sed工具 sed (Stream EDitor&#xff09;是-个强大而简单的文本解析转换工具&#xff0e;可以读取文本&#xff0e;并根据指定的条件对文本内容进行编辑&#xff08;删除&#xff0e;替换&#xff0e;添加、移动等)&#xff0c;最后输出所有行或者仅输出处理…

vue 项目/备案网页/ip网页打包成 apk 安装到平板/手机(含vue项目跨域代理打包成apk后无法访问接口的解决方案)

下载安装HBuilder X编辑器 https://www.dcloud.io/hbuilderx.html 新建 5APP 项目 打开 HBuilder X&#xff0c;新建项目 此处项目名以 ‘test’ 为例 含跨域代理的vue项目改造 若 vue 项目中含跨域代理&#xff0c;如 vue.config.js module.exports {publicPath: "./&…

探索 HTTP 请求的世界:get 和 post 的奥秘(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

【C++项目】ninja报错及解决方法

一、问题描述 C项目中&#xff0c;运行文件时出现以下报错&#xff1a; “ninja: error: ‘D:/Desktop/C Games Chapter 10/10.2 缁ф壙璁块棶鏉冪殑鎺у埗/simple_boss2.cpp’, needed by ‘CMakeFiles/C___Games_Chapter_10_2.dir/10.2_缁ф壙璁块棶鏉冪殑鎺у埗/simple_boss…