当前位置: 首页 > news >正文

Spring Boot + Apache POI 实现 Excel 导出:BOM物料清单生成器(支持中文文件名、样式美化、数据合并)

目录

引言

Apache POI操作Excel的实用技巧

1.合并单元格操作

2.设置单元格样式

1. 创建样式对象

2. 设置边框

3. 设置底色

4. 设置对齐方式

5. 设置字体样式

6.设置自动换行

7. 应用样式到单元格

3. 定位和操作指定单元格

4.实现标签-值的形式

5.列宽设置

1. 设置单个列宽

2. 批量设置多列宽度

6.数据格式化

1. 设置数字格式

2. 设置日期格式

代码展示

1.POM依赖

2.实体类Mode

3.Controller层

4.Service层

获取源码



引言

在最近的MES系统开发中,我们需要导出BOM物料清单,并且客户对样式有较高要求。这就涉及到对POI库样式的精细调整,包括设置表格边框合并单元格设置单元格底色等常见操作。我通过实现一种模板,使得样式设计既美观又实用,并可以根据这个模板创建其他自定义格式。这一模板的主要功能包括:设置Excel表格的边框样式、添加背景色、合并单元格以及采用标签-值的展示形式(如“订单编号:BH000001”)。接下来,我将分享如何通过这种模板实现灵活的Excel导出功能,满足不同业务需求。

如下图是POM清单的一个实现模版:

下面让我们来先学习怎么通过POI库来实现表格边框,合并单元格,设置单元格底色,以及采用标签-值的展示形式这一系列操作!

Apache POI操作Excel的实用技巧

1.合并单元格操作

这个代码片段创建了一个Excel文件,生成了一个名为 "BOM物料清单" 的工作表,在第2行合并了从第1列到第10列的单元格(从第A列到第J列)最后,代码将生成的Excel文件转换为字节数组并返回。

// 使用 try-with-resources 语句,确保 Workbook 在使用完毕后会自动关闭
try (Workbook workbook = new XSSFWorkbook()) {// 创建一个名为 "BOM物料清单" 的工作表Sheet sheet = workbook.createSheet("BOM物料清单");// 创建第2行,行号从0开始,因此创建第2行的行号是1Row titleRow = sheet.createRow(1);// 合并第2行的0列到9列的单元格,CellRangeAddress的参数:起始行、结束行、起始列、结束列sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 9));// 在合并后的区域中设置单元格内容Cell titleCell = titleRow.createCell(0); // 在第1列创建单元格titleCell.setCellValue("BOM物料清单"); // 设置显示内容,例如 "BOM物料清单"// 创建输出流,用于将工作簿内容写入输出流ByteArrayOutputStream outputStream = new ByteArrayOutputStream();// 将工作簿写入到输出流中workbook.write(outputStream);// 返回字节数组,outputStream.toByteArray() 返回Excel文件的二进制数据return outputStream.toByteArray();
}

效果如下:

2.设置单元格样式

// 1. 创建样式对象
CellStyle style = workbook.createCellStyle();// 2. 设置边框
style.setBorderTop(BorderStyle.THIN);    // 上边框
style.setBorderBottom(BorderStyle.THIN); // 下边框
style.setBorderLeft(BorderStyle.THIN);   // 左边框
style.setBorderRight(BorderStyle.THIN);  // 右边框// 3. 设置底色
style.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex()); // 设置颜色
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);           // 设置填充模式// 4. 设置对齐方式
style.setAlignment(HorizontalAlignment.CENTER);      // 水平居中
style.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中// 5. 设置字体样式
Font font = workbook.createFont();
font.setBold(true); // 设置加粗
font.setColor(IndexedColors.RED.getIndex()); // 设置字体颜色为红色
font.setFontHeightInPoints((short) 12); // 设置字体大小
style.setFont(font); // 将字体应用到样式中// 6. 设置自动换行
style.setWrapText(true); // 启用自动换行// 7. 应用样式到单元格
cell.setCellStyle(style);

代码效果:

  • 边框:单元格会有细线的上下左右边框。
  • 底色:单元格背景为浅绿色。
  • 对齐方式:单元格内容会居中对齐(水平和垂直)。
  • 字体样式:字体加粗,颜色为红色,字体大小为12磅。
  • 自动换行:如果单元格内容过长,内容会自动换行。

如下是对每一个小功能的详细解释:

1. 创建样式对象

createCellStyle(): 这个方法是创建一个新的 CellStyle 对象,所有的样式设置都会在这个对象上进行。CellStyle 可以定义单元格的外观,如边框、对齐方式、字体、填充颜色等。

2. 设置边框

setBorderTop:设置单元格的上边框样式为 THIN(细线)。BorderStyle 枚举提供了几种边框样式:THIN(细线)、THICK(粗线)、DOTTED(点线)、DASHED(虚线)等。

setBorderBottom:设置单元格的下边框样式。

setBorderLeft:设置单元格的左边框样式。

setBorderRight:设置单元格的右边框样式。

3. 设置底色

setFillForegroundColor:设置单元格的前景色(填充颜色)。在这里,IndexedColors.LIGHT_GREEN.getIndex() 获取了 IndexedColors 枚举中的 LIGHT_GREEN(浅绿色)的颜色索引值,getIndex() 方法返回该颜色的数字标识。IndexedColors 枚举包括常见颜色,如 YELLOWREDBLUE 等。

setFillPattern(FillPatternType.SOLID_FOREGROUND):设置单元格的填充模式为 SOLID_FOREGROUND,表示填充整个单元格背景色。FillPatternType 还可以选择其他模式,如 NO_FILL(不填充)SOLID_FOREGROUND(完全填充)等。

颜色解释:

LIGHT_GREENIndexedColors 中的一个颜色常量,代表一种浅绿色。可以将单元格的背景色设置为浅绿色,增加表格的视觉效果,使其更具可读性和美观。

4. 设置对齐方式

setAlignment(HorizontalAlignment.CENTER):设置单元格内容在水平方向上的对齐方式。HorizontalAlignment.CENTER 表示水平居中对齐。其他选项包括 LEFT(左对齐)和 RIGHT(右对齐)。

setVerticalAlignment(VerticalAlignment.CENTER):设置单元格内容在垂直方向上的对齐方式。VerticalAlignment.CENTER 表示垂直居中对齐。其他选项包括 TOP(顶部对齐)和 BOTTOM(底部对齐)。

5. 设置字体样式

createFont():通过 workbook.createFont() 创建一个新的 Font 对象,用于设置字体样式。

setBold(true):设置字体加粗。

setColor(IndexedColors.RED.getIndex()):设置字体颜色为红色。IndexedColors.RED.getIndex() 获取了 IndexedColorsRED(红色)的颜色索引。除了 REDIndexedColors 还包含多种颜色,如 BLACKBLUEGREEN 等。

setFontHeightInPoints((short) 12):设置字体的大小为12磅(points)。你可以根据需求调整字体大小。

setFont(font):将字体样式应用到 CellStyle 中,使得字体的加粗、颜色和大小在单元格中生效。

6.设置自动换行

setWrapText(true):启用自动换行功能。当单元格内容过长时,文本会自动换行,以避免内容超出单元格边界。此设置特别有用,尤其是在表格中包含多行文字时。

7. 应用样式到单元格

setCellStyle(style):将之前定义的 style 应用到目标单元格 cell 上。所有在 style 中设置的样式(如边框、底色、字体、对齐方式等)都会在该单元格中生效。

3. 定位和操作指定单元格

通过行列号定位

行号和列号的下标都是从0开始,比如第一行的下标是0,第一列的下标是0

Row row = sheet.createRow(3);  // 注意:行号从0开始,3代表第四行
Cell cell = row.createCell(0); // 列号也从0开始,0代表第一列
cell.setCellValue("单元格内容");
  • sheet.createRow(3):这将创建或返回Excel表格中的第4行(因为行号从0开始,3表示第4行)。
  • row.createCell(0):这将创建或返回第4行的第1列单元格(列号从0开始,0表示第一列)。
  • cell.setCellValue("单元格内容"):为该单元格设置值为 "单元格内容"。

4.实现标签-值的形式

下面这段代码实现了在 Excel 表格中创建标签-值的形式,即每行包含一个标签单元格和一个值单元格。通常这种格式用于展示诸如 "订单编号"、"产品编号" 等信息,并且标签和对应的值是相邻的单元格。以下是代码的详细解释:

private void createLabelValuePair(Row row, int startCol, String label, String value, CellStyle labelStyle, CellStyle valueStyle) {// 创建标签单元格Cell labelCell = row.createCell(startCol);labelCell.setCellValue(label);labelCell.setCellStyle(labelStyle);  // 标签使用一种样式(如带底色)// 创建值单元格Cell valueCell = row.createCell(startCol + 1);valueCell.setCellValue(value);valueCell.setCellStyle(valueStyle);  // 值使用另一种样式(如不带底色)
}

参数说明:

  • Row row:表示当前行对象。在该行上创建标签和值的单元格。
  • int startCol:表示开始列的列号。标签单元格的列号是从 startCol 开始,值单元格紧随其后,列号为 startCol + 1
  • String label:标签文本,例如 "订单编号"、"产品编号" 等。
  • String value:标签对应的值,例如 "BH00000002"、"CP00000002" 等。
  • CellStyle labelStyle:标签单元格的样式,可以设置字体、对齐方式、背景色等。
  • CellStyle valueStyle:值单元格的样式,用于设置不同于标签的样式。

功能:

  • 该方法用于创建一对标签和值,两个单元格位于同一行(row)。标签单元格位于 startCol 列,值单元格位于 startCol + 1 列。
  • 这两个单元格分别应用不同的样式(labelStylevalueStyle),从而使标签和值的显示效果有所区别。标签单元格可能使用不同的字体、颜色、背景等样式,而值单元格则可能有不同的格式。

使用示例:

Row row = sheet.createRow(3); // 注意:行号从0开始,3代表第四行
createLabelValuePair(row, 0, "订单编号", "BH00000002", headerStyle, valueStyle);
createLabelValuePair(row, 2, "产品编号", "CP00000002", headerStyle, valueStyle);

5.列宽设置

1. 设置单个列宽

代码通过 sheet.setColumnWidth() 方法来调整列宽。下面是详细的解释:

sheet.setColumnWidth(columnIndex, 15 * 256); // 15个字符宽度

解释:

  • sheet.setColumnWidth(columnIndex, 15 * 256):该方法设置 Excel 中指定列的宽度。
    • columnIndex:表示列的索引,Excel 中列的索引从 0 开始。例如,0 表示 A 列,1 表示 B 列,以此类推。
    • 15 * 256:列宽的单位是 "字符宽度",但在 POI 中,单位是字符宽度的 1/256,因此需要乘以 256
      • 15 表示列宽为 15 个字符宽度(即单元格中可以容纳15个字符长度)。
      • 256 是 POI 中列宽的缩放因子,表示字符宽度单位是 1/256 的一个字符宽度。所以 15 * 256 表示列宽为 15 个字符的宽度。

在这个例子中,sheet.setColumnWidth(columnIndex, 15 * 256) 将设置列的宽度为15个字符的宽度,columnIndex 列号是动态指定的。

2. 批量设置多列宽度

private void setColumnWidths(Sheet sheet) {int[] widths = {15, 15, 15, 12, 12, 12, 15, 12, 15, 12};for (int i = 0; i < widths.length; i++) {sheet.setColumnWidth(i, widths[i] * 256);}
}

解释:

  • int[] widths = {15, 15, 15, 12, 12, 12, 15, 12, 15, 12};

    • 这是一个整型数组 widths,它存储了每一列的宽度设置值。数组中的每个值代表对应列的宽度(单位是字符的数量)。
    • 15, 15, 15 等表示前面列宽设置为 15 个字符,12, 12, 12 等表示后面列宽设置为 12 个字符。
  • for (int i = 0; i < widths.length; i++) { ... }

    • 这是一个循环,用于遍历 widths 数组中的每个元素。
    • widths.length 返回数组的长度(此处为 10),所以循环会执行 10 次,每次处理一个列的宽度。
  • sheet.setColumnWidth(i, widths[i] * 256);

    • i 是列索引,因此 i09(共10列)。
    • widths[i] 获取数组中当前索引位置的宽度值,将这个值乘以 256 以得到正确的列宽单位(字符宽度的 1/256)。
    • sheet.setColumnWidth(i, widths[i] * 256) 将依次设置每一列的宽度,确保列宽符合指定的字符数。

6.数据格式化

这段代码展示了如何在 Apache POI 中设置 Excel 单元格的数据格式,具体包括数字格式和日期格式的设置。以下是对每一部分的详细解释:

1. 设置数字格式

CellStyle numberStyle = workbook.createCellStyle();
DataFormat format = workbook.createDataFormat();
numberStyle.setDataFormat(format.getFormat("#,##0.00"));

解释:

  • CellStyle numberStyle = workbook.createCellStyle();

    • 这行代码创建一个新的 CellStyle 对象(numberStyle),该对象用于设置单元格的样式。
    • CellStyle 用于控制单元格的外观,比如字体、边框、对齐方式以及数据格式等。
  • DataFormat format = workbook.createDataFormat();

    • createDataFormat()Workbook 类的一个方法,用于创建一个 DataFormat 对象。DataFormat 类用于定义单元格的数据格式(如日期、数字、货币等)。
    • format 对象将用于设置不同类型的格式,允许将格式应用于 CellStyle 中。
  • numberStyle.setDataFormat(format.getFormat("#,##0.00"));

    • setDataFormat() 方法用于为 CellStyle 设置数据格式。
    • format.getFormat("#,##0.00") 使用 DataFormat 对象来定义具体的数字格式。这段格式表示:
      • #,##0.00:这是数字的格式模式,表示数字应该使用千位分隔符(,),并且保留两位小数(.00)。例如,数字 1234567.89 会显示为 1,234,567.89
      • # 是占位符,表示数字的每个位置(但如果没有值,它就不显示)。
      • 0 表示即使数字为零,也会显示该位置的零。
      • .00 表示保留两位小数,即使实际数据没有小数部分,也会显示为 0.00

2. 设置日期格式

CellStyle dateStyle = workbook.createCellStyle();
dateStyle.setDataFormat(format.getFormat("yyyy/mm/dd"));

解释:

  • CellStyle dateStyle = workbook.createCellStyle();

    • 这行代码创建一个新的 CellStyle 对象(dateStyle),用于设置日期单元格的格式。
    • 这个 CellStyle 对象将应用于日期格式的单元格。
  • dateStyle.setDataFormat(format.getFormat("yyyy/mm/dd"));

    • setDataFormat() 方法为 dateStyle 设置数据格式。
    • format.getFormat("yyyy/mm/dd") 使用 DataFormat 对象来设置日期的格式。具体格式为:
      • yyyy/mm/dd:这是日期的格式模式,表示日期应该显示为年-月-日的格式。
        • yyyy 表示四位年份(例如 2025)。
        • mm 表示两位月份(例如 01 表示一月,12 表示十二月)。
        • dd 表示两位日期(例如 01 表示第一天,31 表示最后一天)。
      • 例如,日期 2025/01/17 会显示为 2025/01/17

总结:

这段代码展示了如何为 Excel 单元格设置数字和日期格式,具体包括:

  1. 数字格式:将单元格内容设置为数字格式,使用千位分隔符并保留两位小数(例如:1,234,567.89)。
  2. 日期格式:将单元格内容设置为日期格式,显示为年-月-日(例如:2025/01/17)。

代码展示

1.POM依赖

POM依赖需要引入org.apache.poi

        <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>5.2.3</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency>

2.实体类Mode

BOM清单标题头

public class BOMHeader {private String orderNumber;        // 订单编号private String productNumber;      // 产品编号private String productName;        // 产品名称private String specification;      // 规格型号private Integer orderQuantity;     // 订单数量private String planStartDate;      // 计划投产日期private Integer productionCycle;   // 计划生产周期private String planEndDate;        // 计划截止日期private String deliveryDate;       // 订单交期private Double totalCost;          // 合计成本public BOMHeader(String orderNumber, String productNumber, String productName, String specification, Integer orderQuantity, String planStartDate, Integer productionCycle, String planEndDate, String deliveryDate, Double totalCost) {this.orderNumber = orderNumber;this.productNumber = productNumber;this.productName = productName;this.specification = specification;this.orderQuantity = orderQuantity;this.planStartDate = planStartDate;this.productionCycle = productionCycle;this.planEndDate = planEndDate;this.deliveryDate = deliveryDate;this.totalCost = totalCost;}public BOMHeader() {}public String getOrderNumber() {return orderNumber;}public void setOrderNumber(String orderNumber) {this.orderNumber = orderNumber;}public String getProductNumber() {return productNumber;}public void setProductNumber(String productNumber) {this.productNumber = productNumber;}public String getProductName() {return productName;}public void setProductName(String productName) {this.productName = productName;}public String getSpecification() {return specification;}public void setSpecification(String specification) {this.specification = specification;}public Integer getOrderQuantity() {return orderQuantity;}public void setOrderQuantity(Integer orderQuantity) {this.orderQuantity = orderQuantity;}public String getPlanStartDate() {return planStartDate;}public void setPlanStartDate(String planStartDate) {this.planStartDate = planStartDate;}public Integer getProductionCycle() {return productionCycle;}public void setProductionCycle(Integer productionCycle) {this.productionCycle = productionCycle;}public String getPlanEndDate() {return planEndDate;}public void setPlanEndDate(String planEndDate) {this.planEndDate = planEndDate;}public String getDeliveryDate() {return deliveryDate;}public void setDeliveryDate(String deliveryDate) {this.deliveryDate = deliveryDate;}public Double getTotalCost() {return totalCost;}public void setTotalCost(Double totalCost) {this.totalCost = totalCost;}
}

BOM清单列表

public class BOMItem {private String materialCode;    // 料号private String name;           // 品名private String modelNumber;    // 型号private String unit;           // 计量单位private Integer quantity;      // 用量private String manufacturer;   // 厂家/品牌private String channel;        // 途径/渠道private Double unitPrice;      // 单价private Double total;          // 合计private String remarks;        // 备注public BOMItem(String materialCode, String name, String modelNumber, String unit, Integer quantity, String manufacturer, String channel, Double unitPrice, Double total, String remarks) {this.materialCode = materialCode;this.name = name;this.modelNumber = modelNumber;this.unit = unit;this.quantity = quantity;this.manufacturer = manufacturer;this.channel = channel;this.unitPrice = unitPrice;this.total = total;this.remarks = remarks;}public BOMItem() {}public String getMaterialCode() {return materialCode;}public void setMaterialCode(String materialCode) {this.materialCode = materialCode;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getModelNumber() {return modelNumber;}public void setModelNumber(String modelNumber) {this.modelNumber = modelNumber;}public String getUnit() {return unit;}public void setUnit(String unit) {this.unit = unit;}public Integer getQuantity() {return quantity;}public void setQuantity(Integer quantity) {this.quantity = quantity;}public String getManufacturer() {return manufacturer;}public void setManufacturer(String manufacturer) {this.manufacturer = manufacturer;}public String getChannel() {return channel;}public void setChannel(String channel) {this.channel = channel;}public Double getUnitPrice() {return unitPrice;}public void setUnitPrice(Double unitPrice) {this.unitPrice = unitPrice;}public Double getTotal() {return total;}public void setTotal(Double total) {this.total = total;}public String getRemarks() {return remarks;}public void setRemarks(String remarks) {this.remarks = remarks;}
}

3.Controller层

import com.e.toexcel.model.BOMHeader;
import com.e.toexcel.model.BOMItem;
import com.e.toexcel.service.BOMExcelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/bom")
public class BOMController {@Autowiredprivate BOMExcelService bomExcelService;@GetMapping("/export")public ResponseEntity<byte[]> exportBOM() {try {// 创建示例数据BOMHeader header = createSampleHeader();List<BOMItem> items = createSampleItems();// 生成Excel文件byte[] excelContent = bomExcelService.generateBOMExcel(header, items);// 设置响应头HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);// 使用 URLEncoder 对文件名进行编码String filename = URLEncoder.encode("BOM物料清单.xlsx", StandardCharsets.UTF_8.name());// 替换空格编码filename = filename.replaceAll("\\+", "%20");// 设置 Content-Disposition 头headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + filename);return ResponseEntity.ok().headers(headers).body(excelContent);} catch (Exception e) {e.printStackTrace(); // 添加日志输出以便调试return ResponseEntity.internalServerError().build();}}private BOMHeader createSampleHeader() {return new BOMHeader("BH00000002","CP00000002","自动包装机","CS5506",80000,"2024/3/15",25,"2024/4/10","2024/4/20",98560000.00);}private List<BOMItem> createSampleItems() {List<BOMItem> items = new ArrayList<>();// 添加所有示例数据items.add(createBOMItem("WL000101", "传送带", "ZJ000101", "个", 40000, "ABC品牌", "采购链接: yyyy", 120.00));items.add(createBOMItem("WL000102", "电机", "ZJ000102", "个", 80000, "DEF品牌", "自制生产", 0.00));items.add(createBOMItem("WL000103", "控制器", "ZJ000103", "个", 40000, "GHI品牌", "采购链接: yyyy", 350.00));items.add(createBOMItem("WL000104", "感应器", "ZJ000104", "个", 160000, "JKL品牌", "采购链接: yyyy", 80.00));items.add(createBOMItem("WL000105", "支架", "ZJ000105", "个", 80000, "MNO品牌", "自制生产", 0.00));items.add(createBOMItem("WL000106", "螺丝套件", "ZJ000106", "个", 320000, "PQR品牌", "采购链接: yyyy", 25.00));items.add(createBOMItem("WL000107", "线缆", "ZJ000107", "个", 240000, "STU品牌", "采购链接: yyyy", 45.00));items.add(createBOMItem("WL000108", "外壳", "ZJ000108", "个", 80000, "VWX品牌", "自制生产", 0.00));items.add(createBOMItem("WL000109", "显示屏", "ZJ000109", "个", 80000, "YZA品牌", "采购链接: yyyy", 280.00));items.add(createBOMItem("WL000110", "按钮组", "ZJ000110", "个", 160000, "BCD品牌", "采购链接: yyyy", 95.00));items.add(createBOMItem("WL000111", "密封圈", "ZJ000111", "个", 240000, "EFG品牌", "采购链接: yyyy", 35.00));items.add(createBOMItem("WL000112", "铭牌", "ZJ000112", "个", 80000, "HIJ品牌", "采购链接: yyyy", 15.00));items.add(createBOMItem("WL000113", "包装材料", "ZJ000113", "个", 80000, "KLM品牌", "采购链接: yyyy", 12.00));return items;}private BOMItem createBOMItem(String code, String name, String model, String unit, int quantity, String manufacturer, String channel, double price) {double total = channel.equals("自制生产") ? 0.00 : price * quantity;return new BOMItem(code,name,model,unit,quantity,manufacturer,channel,price,total,""  // remarks);}
} 

4.Service层

package com.e.toexcel.service;import com.e.toexcel.model.BOMHeader;
import com.e.toexcel.model.BOMItem;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;@Service
public class BOMExcelService {private CellStyle valueStyle;  // 添加成员变量private void createTitle(Sheet sheet, CellStyle style) {Row titleRow = sheet.createRow(1);// 为所有要合并的单元格创建样式for (int i = 0; i < 10; i++) {Cell cell = titleRow.createCell(i);cell.setCellStyle(style);// 只在第一个单元格设置值if (i == 0) {cell.setCellValue("BOM物料清单");}}// 合并单元格sheet.addMergedRegion(new CellRangeAddress(1, 1, 0, 9));}private void createBasicInfo(Sheet sheet, BOMHeader header, CellStyle style) {// 第一行基本信息Row row1 = sheet.createRow(3);createHeaderCell(row1, 0, "订单编号", header.getOrderNumber(), style);createHeaderCell(row1, 2, "产品编号", header.getProductNumber(), style);createHeaderCell(row1, 4, "产品名称", header.getProductName(), style);createHeaderCell(row1, 6, "规格型号", header.getSpecification(), style);createHeaderCell(row1, 8, "订单数量", String.valueOf(header.getOrderQuantity()), style);// 第二行基本信息Row row2 = sheet.createRow(4);createHeaderCell(row2, 0, "计划投产日期", header.getPlanStartDate(), style);createHeaderCell(row2, 2, "计划生产周期", String.valueOf(header.getProductionCycle()), style);createHeaderCell(row2, 4, "计划截止日期", header.getPlanEndDate(), style);createHeaderCell(row2, 6, "订单交期", header.getDeliveryDate(), style);createHeaderCell(row2, 8, "合计成本", String.format("%.2f", header.getTotalCost()), style);}private void createHeaderCell(Row row, int col, String label, String value, CellStyle headerStyle) {Cell labelCell = row.createCell(col);labelCell.setCellValue(label);labelCell.setCellStyle(headerStyle);Cell valueCell = row.createCell(col + 1);valueCell.setCellValue(value);valueCell.setCellStyle(this.valueStyle);}private void createTableHeader(Sheet sheet, CellStyle style) {Row headerRow = sheet.createRow(6);String[] headers = {"料号", "品名", "型号", "计量单位", "用量", "厂家/品牌", "途径/渠道", "单价", "合计", "备注"};for (int i = 0; i < headers.length; i++) {Cell cell = headerRow.createCell(i);cell.setCellValue(headers[i]);cell.setCellStyle(style);}}private void fillData(Sheet sheet, List<BOMItem> items, CellStyle style) {int rowNum = 7;for (BOMItem item : items) {Row row = sheet.createRow(rowNum++);row.createCell(0).setCellValue(item.getMaterialCode());row.createCell(1).setCellValue(item.getName());row.createCell(2).setCellValue(item.getModelNumber());row.createCell(3).setCellValue(item.getUnit());row.createCell(4).setCellValue(item.getQuantity());row.createCell(5).setCellValue(item.getManufacturer());row.createCell(6).setCellValue(item.getChannel());row.createCell(7).setCellValue(item.getUnitPrice());row.createCell(8).setCellValue(item.getTotal());row.createCell(9).setCellValue(item.getRemarks());for (int i = 0; i < 10; i++) {row.getCell(i).setCellStyle(style);}}}private void createNote(Sheet sheet, CellStyle style) {Row noteRow = sheet.createRow(sheet.getLastRowNum() + 1);// 创建所有需要合并的单元格并设置样式for (int i = 0; i < 10; i++) {Cell cell = noteRow.createCell(i);cell.setCellStyle(style);// 只在第一个单元格设置值if (i == 0) {cell.setCellValue("说明:采购渠道请与采购部门进行确认,如物料采购困难,请及时与研发人员沟通更换其他替代品");}}// 合并单元格sheet.addMergedRegion(new CellRangeAddress(noteRow.getRowNum(), noteRow.getRowNum(), 0, 9));}private void setColumnWidths(Sheet sheet) {int[] widths = {15, 15, 15, 12, 12, 12, 15, 12, 15, 12};for (int i = 0; i < widths.length; i++) {sheet.setColumnWidth(i, widths[i] * 256);}}public byte[] generateBOMExcel(BOMHeader header, List<BOMItem> items) throws IOException {try (Workbook workbook = new XSSFWorkbook()) {Sheet sheet = workbook.createSheet("BOM物料清单");// 创建样式CellStyle headerStyle = createHeaderStyle(workbook);CellStyle normalStyle = createNormalStyle(workbook);this.valueStyle = createValueStyle(workbook);  // 初始化值样式// 设置标题createTitle(sheet, headerStyle);// 设置基本信息createBasicInfo(sheet, header, headerStyle);// 创建表头createTableHeader(sheet, headerStyle);// 填充数据fillData(sheet, items, normalStyle);// 添加说明createNote(sheet, normalStyle);// 调整列宽setColumnWidths(sheet);// 导出ByteArrayOutputStream outputStream = new ByteArrayOutputStream();workbook.write(outputStream);return outputStream.toByteArray();}}// 该方法用于创建 Excel 表头的单元格样式private CellStyle createHeaderStyle(Workbook workbook) {// 创建一个新的单元格样式CellStyle style = workbook.createCellStyle();// 设置单元格的前景填充颜色为浅绿style.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());// 设置填充模式为纯色填充style.setFillPattern(FillPatternType.SOLID_FOREGROUND);// 设置上边框为细线style.setBorderTop(BorderStyle.THIN);// 设置下边框为细线style.setBorderBottom(BorderStyle.THIN);// 设置左边框为细线style.setBorderLeft(BorderStyle.THIN);// 设置右边框为细线style.setBorderRight(BorderStyle.THIN);// 设置水平对齐方式为居中style.setAlignment(HorizontalAlignment.CENTER);// 设置垂直对齐方式为居中style.setVerticalAlignment(VerticalAlignment.CENTER);// 返回创建好的单元格样式return style;}// 该方法用于创建 Excel 普通单元格的样式private CellStyle createNormalStyle(Workbook workbook) {// 创建一个新的单元格样式CellStyle style = workbook.createCellStyle();// 设置上边框为细线style.setBorderTop(BorderStyle.THIN);// 设置下边框为细线style.setBorderBottom(BorderStyle.THIN);// 设置左边框为细线style.setBorderLeft(BorderStyle.THIN);// 设置右边框为细线style.setBorderRight(BorderStyle.THIN);// 设置水平对齐方式为居中style.setAlignment(HorizontalAlignment.CENTER);// 设置垂直对齐方式为居中style.setVerticalAlignment(VerticalAlignment.CENTER);// 返回创建好的单元格样式return style;}// 此方法用于创建 Excel 中存储值的单元格的样式private CellStyle createValueStyle(Workbook workbook) {// 创建一个新的单元格样式对象CellStyle style = workbook.createCellStyle();// 设置上边框为细线style.setBorderTop(BorderStyle.THIN);// 设置下边框为细线style.setBorderBottom(BorderStyle.THIN);// 设置左边框为细线style.setBorderLeft(BorderStyle.THIN);// 设置右边框为细线style.setBorderRight(BorderStyle.THIN);// 设置单元格内容的水平对齐方式为居中style.setAlignment(HorizontalAlignment.CENTER);// 设置单元格内容的垂直对齐方式为居中style.setVerticalAlignment(VerticalAlignment.CENTER);// 将创建好的单元格样式对象返回return style;}
} 

获取源码

源码地址:源码地址

写到这里也就结束了,如果你觉得此文章对你有所帮助的话就一键三连,在下谢谢您嘞!

相关文章:

Spring Boot + Apache POI 实现 Excel 导出:BOM物料清单生成器(支持中文文件名、样式美化、数据合并)

目录 引言 Apache POI操作Excel的实用技巧 1.合并单元格操作 2.设置单元格样式 1. 创建样式对象 2. 设置边框 3. 设置底色 4. 设置对齐方式 5. 设置字体样式 6.设置自动换行 7. 应用样式到单元格 3. 定位和操作指定单元格 4.实现标签-值的形式 5.列宽设置 1. 设…...

OpenVela——专为AIoT领域打造的开源操作系统

目录 一、系统背景与开源 1.1. 起源 1.2. 开源 二、系统特点 2.1. 轻量化 2.2. 标准兼容性 2.3. 安全性 2.4. 高度可扩展性 三、技术支持与功能 3.1. 架构支持 3.2. 异构计算支持 3.3. 全面的连接套件 3.4. 开发者工具 四、应用场景与优势 4.1. 应用场景 4.2. …...

02UML图(D1_结构图)

目录 学习前言 ---------------------------------- 讲解一&#xff1a;类图 一、类图的组成结构 1. 类(Class) 1.1. 类的成员变量的表示方式 1.2. 类的成员方法的表示方式 2. 接口&#xff08;Interface&#xff09; 3. 包&#xff08;Package&#xff09; 二、UML类…...

二十三种设计模式-装饰器模式

一、定义与核心思想 装饰器模式是一种结构型设计模式&#xff0c;其核心思想是动态地给一个对象添加一些额外的职责。通过这种方式&#xff0c;可以在不改变原有对象结构的基础上&#xff0c;灵活地增加新的功能&#xff0c;使得对象的行为可以得到扩展&#xff0c;同时又保持…...

SSM课设-酒店管理系统功能设计

【课设者】SSM课设-酒店管理系统 分为用户端管理员端 技术栈: 后端: Spring Spring MVC MyBatis Mysql JSP 前端: HtmlCssJavaScriptAjax 功能: 用户端主要功能包括&#xff1a; 登录注册 客房预订 客房评论 首页 管理员端主要功能包括&#xff1a; 会员信息管理 客房信息…...

R语言的文件操作

R语言的文件操作 引言 在数据科学和分析的过程中&#xff0c;文件操作是不可或缺的一部分。R语言作为一种强大的统计计算和图形作图的编程语言&#xff0c;提供了丰富的文件操作函数&#xff0c;使得用户能够方便地读取和保存数据。本文将详细介绍R语言中的文件操作&#xff…...

[javaWeb]初识Web

将该图片在浏览器中打印出来 代码&#xff1a; <html> <head> <title>HTML初识</title> </head> <body> <h1>猫猫</h1> <img src "img/1.jpg"> </body> &l…...

基于微信小程序的摄影竞赛系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

.netframwork模拟启动webapi服务并编写对应api接口

在.NET Framework环境中模拟启动Web服务&#xff0c;可以使用几种不同的方法。一个常见的选择是利用HttpListener类来创建一个简单的HTTP服务器&#xff0c;或者使用Owin/Katana库来自托管ASP.NET Web API或MVC应用。下面简要介绍Owin/Katana示例代码。这种方法更加灵活&#x…...

Go语言之路————条件控制:if、for、switch

Go语言之路————if、for、switch 前言ifforswitchgoto和label 前言 我是一名多年Java开发人员&#xff0c;因为工作需要现在要学习go语言&#xff0c;Go语言之路是一个系列&#xff0c;记录着我从0开始接触Go&#xff0c;到后面能正常完成工作上的业务开发的过程&#xff0…...

54,【4】BUUCTF WEB GYCTF2020Ezsqli

进入靶场 吓我一跳&#xff0c;但凡放个彭于晏我都不说啥了 提交个1看看 1 and 11 1# 还尝试了很多&#xff0c;不过都被过滤了&#xff0c;头疼 看看别人的WP 竟然要写代码去跑&#xff01;&#xff01;&#xff01;&#xff0c;不会啊&#xff0c;先用别人的代码吧&#xf…...

在线图片压缩工具

在线图片压缩工具&#xff0c;无需登录&#xff0c;无需成本&#xff0c;用完就走。 包括中文和英文版本。 官网地址&#xff1a; https://compress.openai2025.com/ 效果&#xff1a;...

快手极速版如何查找ip归属地?怎么关掉

在数字化时代&#xff0c;个人隐私的保护成为了广大用户关注的焦点。快手极速版作为一款备受欢迎的短视频应用&#xff0c;其IP归属地的显示与关闭功能自然也成了用户热议的话题。本文将详细介绍如何在快手极速版中查找IP归属地以及如何关闭IP属地显示&#xff0c;帮助用户更好…...

精准掌握:Nginx匹配规则及其优先级解析

Nginx作为一款高性能的HTTP和反向代理服务器&#xff0c;其配置文件的匹配规则及优先级设置对于实现精确的请求路由和资源分配至关重要。本文将深入探讨Nginx的匹配规则及其优先级&#xff0c;帮助读者更好地理解和应用这些配置。 一、Nginx匹配规则概述 Nginx的匹配规则主要…...

在VS2022中用C++连接MySQL数据库读取数据库乱码问题

1.正确安装mysql 安装之后的配置文件 2.在VS2022中进行相关配置 &#xff08;1&#xff09;右键项目&#xff0c;打开属性 注意是右键项目&#xff0c;不是.cpp文件 &#xff08;2&#xff09;配置属性-> VC目录 -> 包含目录 ->添加头文件路径&#xff08;如图&am…...

RocketMQ源码分析之事务消息分析

rocketMQ事务消息原理概述 RocketMQ采用两阶段提交&#xff08;2PC&#xff09;的思想来实现事务消息&#xff0c;当事务消息失败或者超时&#xff0c;同时采用补偿的方式处理这个问题。这两个阶段分别为正常事务消息的发送与提交以及事务消息的补偿。我们看看官方文档给的事务…...

2025.1.19机器学习笔记:PINN文献精读

第三十周周报 一、文献阅读题目信息摘要Abstract创新点物理背景网络框架实验实验一&#xff1a;直道稳定流条件实验二&#xff1a;环状网络中的非稳定流条件 结论缺点及展望 二、代码实践总结 一、文献阅读 题目信息 题目&#xff1a;《Enhanced physics-informed neural net…...

大文件上传服务-后端V1V2

文章目录 大文件上传概述:minio分布式文件存储使用的一些技术校验MD5的逻辑 uploadV1 版本 1uploadv2 版本 2 大文件上传概述: 之前项目做了一个文件上传的功能,最近看到有面试会具体的问这个上传功能的细节&#xff0c;把之前做的项目拿过来总结一下&#xff0c;自己写的一个…...

docker 基础语法学习,K8s基础语法学习,零基础学习

下面是关于Docker和Kubernetes的基础语法学习资料&#xff0c;包括一些关键概念和示例代码。 Docker 基础语法 1. 安装 Docker 首先&#xff0c;你需要安装 Docker。以下是不同操作系统上的安装指南&#xff1a; Windows/Mac: 下载并安装 Docker Desktop。 Linux: 根据你的…...

【网络协议】RFC3164-The BSD syslog Protocol

引言 Syslog常被称为系统日志或系统记录&#xff0c;是一种标准化的协议&#xff0c;用于网络设备、服务器和应用程序向中央Syslog服务器发送日志消息。互联网工程任务组&#xff08;IETF&#xff09;发布的RFC 3164&#xff0c;专门定义了BSD Syslog协议的规范和实现方式。通…...

MongoDB深度解析与实践案例

MongoDB深度解析与实践案例 在当今大数据与云计算盛行的时代,NoSQL数据库以其灵活的数据模型、水平扩展能力和高性能,成为处理海量数据的重要工具之一。MongoDB,作为NoSQL数据库的杰出代表,凭借其面向文档的存储结构、强大的查询语言以及丰富的生态系统,赢得了众多开发者…...

C语言从零到精通:常用运算符完全指南,掌握算术、逻辑与关系运算

系列文章目录 01-C语言从零到精通&#xff1a;常用运算符完全指南&#xff0c;掌握算术、逻辑与关系运算 文章目录 系列文章目录前言一、C语言的起源与应用领域1.1 C语言的起源1.2 C语言的应用领域1.2.1 操作系统开发1.2.2 嵌入式系统1.2.3 编译器开发1.2.4 游戏开发与图形处理…...

ArkUI概述

鸿蒙操作系统&#xff08;HarmonyOS&#xff09;是华为公司推出的一款面向未来、面向全场景的分布式操作系统。它不仅能够支持各种不同的设备&#xff0c;从手机、平板到智能穿戴和智能家居产品&#xff0c;而且为开发者提供了一套统一的开发环境和工具链。对于想要深入鸿蒙开发…...

浅谈计算机网络03 | 现代网络组成

现代网络组成 一 、网络生态体系1.1网络生态系统的多元主体1.2 网络接入设施的多样类型 二、现代网络的典型体系结构解析三、高速网络技术3.1 以太网技术3.2 Wi-Fi技术的深度剖析3.2.1 应用场景的多元覆盖3.2.2 标准升级与性能提升 3.3 4G/5G蜂窝网的技术演进3.3.1 蜂窝技术的代…...

在线图片马赛克处理工具

在线图片马赛克处理工具&#xff0c;无需登录&#xff0c;无需费用&#xff0c;用完就走。 包括中文和英文版本 官网地址&#xff1a; https://mosaic.openai2025.com...

文件上传 分片上传

分片上传则是将一个大文件分割成多个小块分别上传&#xff0c;最后再由服务器合并成完整的文件。这种做法的好处是可以并行处理多个小文件&#xff0c;提高上传效率&#xff1b;同时&#xff0c;如果某一部分上传失败&#xff0c;只需要重传这一部分&#xff0c;不影响其他部分…...

网络安全---CMS指纹信息实战

CMS简介 CMS&#xff08;Content Management System&#xff09;指的是内容管理系统&#xff0c;如WordPress、Joomla等。CMS系统非常常见&#xff0c;几乎所有大型网站都使用CMS来管理其网站的内容。由于常见CMS的漏洞较多&#xff0c;因此黑客将不断尝试利用这些漏洞攻击CMS…...

Ubuntu 24.04 LTS 系统语言英文改中文

Ubuntu 24.04 LTS 修改软件源 Ubuntu 更改软件源 修改语言 无需输入命令&#xff0c;为Ubuntu 24.04系统添加中文智能拼音输入法 在 setting 的 system 中按下图操作 点击“Apply Changes”。需要管理员密码&#xff0c;安装完成后&#xff0c;退出登录&#xff0c;重新登…...

信创在医疗领域的应用:开启医疗信息化新时代

信创在医疗领域的应用&#xff1a;开启医疗信息化新时代 信创在医疗领域的应用&#xff1a;开启医疗信息化新时代信创医疗自助一体机杭医基于信创底座的健康医疗大数据平台厦门大学附属成功医院基于海光CPU的信创改造中科可控基于海光CPU的智慧医疗解决方案 信创在医疗领域的应…...

力扣-数组-303 区域和检索-数组不可变

解析 题目有点费解&#xff0c;大致应该是给出区间内的和&#xff0c;然后维护一个前缀和&#xff0c;为了防止越界&#xff0c;先填一个0进去&#xff0c;在构建的时候也要注意此时构建的dp的下标是i1&#xff0c;所以加的前缀和的下标是i。 代码 class NumArray { public:…...

【CSS】---- CSS 实现超过固定高度后出现展开折叠按钮

1. 实现效果 2. 实现方法 使用 JS 获取盒子的高度&#xff0c;来添加对应的按钮和样式&#xff1b;使用 CSS 的浮动效果&#xff0c;参考CSS 实现超过固定高度后出现展开折叠按钮&#xff1b;使用容器查询 – container 语法&#xff1b;使用 clamp 函数进行样式判断。 3. 优…...

二十项零信任相关的前沿和趋势性技术-MASQUE

影响力评级&#xff1a;较低 市场渗透率&#xff1a;不到目标受众的 1% 成熟度&#xff1a;孵化 定义&#xff1a;基于QUIC加密的多路复用应用程序底层 (MASQUE) 是一个 IETF 标准草案&#xff0c;可实现流量的安全传输和代理。 MASQUE全称为&#xff1a;Multiplexed Appli…...

【Docker】使用Dev Container进行开发

工作区 Dev Container 设置 新建一个文件夹 ./devcontainer 然后下面放 devcontainer.json 然后安装 vscode dev container 插件&#xff0c;然后 CtrlShiftP 启动 Container {"name": "PyTorch-Julia Development","image": "x66ccff/p…...

搭建一个基于Spring Boot的数码分享网站

搭建一个基于Spring Boot的数码分享网站可以涵盖多个功能模块&#xff0c;例如用户管理、数码产品分享、评论、点赞、收藏、搜索等。以下是一个简化的步骤指南&#xff0c;帮助你快速搭建一个基础的数码分享平台。 — 1. 项目初始化 使用 Spring Initializr 生成一个Spring …...

在线json格式化工具

在线json格式化工具,包括中文和英文版本,无需登录&#xff0c;无需费用&#xff0c;用完就走。 官网地址&#xff1a; https://json.openai2025.com 效果如下&#xff1a;...

leetcode300.最长递增子序列

给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。 示例 1&…...

【个人学习记录】软件开发生命周期(SDLC)是什么?

软件开发生命周期&#xff08;Software Development Life Cycle&#xff0c;SDLC&#xff09;是一个用于规划、创建、测试和部署信息系统的结构化过程。它包含以下主要阶段&#xff1a; 需求分析&#xff08;Requirements Analysis&#xff09; 收集并分析用户需求定义系统目标…...

CTE与临时表:优劣势对比及使用场景分析

在数据库开发中&#xff0c;尤其是在复杂查询和优化中&#xff0c;**公共表表达式&#xff08;CTE&#xff09;和临时表&#xff08;Temporary Table&#xff09;**是两种常用的工具。尽管它们的功能有些相似&#xff0c;都是为了处理中间结果集&#xff0c;但它们的优劣势和使…...

Kali环境变量技巧(The Environment Variable Technique Used by Kali

Kali环境变量技巧 朋友们好&#xff0c;我们今天继续更新《黑客视角下的Kali Linux的基础与网络管理》中的管理用户环境变量。为了充分利用我们的黑客操作系统Kali Linux&#xff0c;我们需要理解和善于使用环境变量&#xff0c;这样会使我们的工具更具便利&#xff0c;甚至具…...

Ubuntu 24.04 LTS linux 文件权限

Ubuntu 24.04 LTS 文件权限 读权限 &#xff1a;允许查看文件的内容。写权限 (w)&#xff1a;允许修改文件的内容。执行权限 (x)&#xff1a;允许执行文件&#xff08;对于目录来说&#xff0c;是进入目录的权限&#xff09;。 文件权限通常与三类用户相关联&#xff1a; 文…...

多个版本JAVA切换(学习笔记)

多个版本JAVA切换 很多时候&#xff0c;我们电脑上会安装多个版本的java版本&#xff0c;java8&#xff0c;java11&#xff0c;java17等等&#xff0c;这时候如果想要切换java的版本&#xff0c;可以按照以下方式进行 1.检查当前版本的JAVA 同时按下 win r 可以调出运行工具…...

AI刷题-最小替换子串长度、Bytedance Tree 问题

目录 一、最小替换子串长度 问题描述 输入格式 输出格式 输入样例 1 输出样例 1 输入样例 2 输出样例 2 解题思路&#xff1a; 问题理解 数据结构选择 算法步骤 最终代码&#xff1a; 运行结果&#xff1a; 二、Bytedance Tree 问题 问题描述 输入格式 输…...

Android 项目依赖冲突问题:Duplicate class found in modules

问题描述与处理处理 1、问题描述 plugins {id com.android.application }android {compileSdk 34defaultConfig {applicationId "com.my.dialog"minSdk 21targetSdk 34versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.run…...

Webpack简述

一、为什么要构建工具 人类喜欢书写的代码以及开发方式计算机不喜欢&#xff0c;构建工具的作用就是让人类舒舒服服写自己喜欢的代码&#xff0c;然后一打包生成计算机喜欢的代码 第一个webpack自身仅仅是将我们引入的模块打包成一个文件&#xff08;编译import&#xff09;&am…...

ARM GCC编译器

ARM GCC编译器&#xff08;GNU Compiler Collection for ARM&#xff09;是GNU项目的一部分&#xff0c;专门用于编译针对ARM架构的代码。它是一个开源的工具链&#xff0c;支持多种编程语言&#xff0c;包括C、C和汇编语言。以下是关于ARM GCC编译器的详细解释及其作用&#x…...

CSS3 3D 转换介绍

CSS3 中的 3D 转换提供了一种在二维屏幕上呈现三维效果的方式&#xff0c;主要包括translate3d、rotate3d、scale3d等转换函数&#xff0c;下面来详细介绍&#xff1a; 1. 3D 转换的基本概念 坐标系 在 CSS3 的 3D 空间中&#xff0c;使用的是右手坐标系。X 轴是水平方向&…...

关于 Cursor 的一些学习记录

文章目录 1. 写在最前面2. Prompt Design2.1 Priompt v0.1&#xff1a;提示设计库的首次尝试2.2 注意事项 3. 了解 Cursor 的 AI 功能3.1 问题3.2 答案 4. cursor 免费功能体验5. 写在最后面6. 参考资料 1. 写在最前面 本文整理了一些学习 Cursor 过程中读到的或者发现的感兴趣…...

3. 后端验证前端Token

书接上回&#xff0c;后端将token返回给前端&#xff0c;前端存入cookie&#xff0c;每次前端给后端发送请求&#xff0c;后端是如何验证的。 若依是用过滤器来实现对请求的验证&#xff0c;过滤器的简单理解是每次发送请求的时候先发送给过滤器执行逻辑判断以及处理&#xff0…...

【LLM】Openai-o1及o1类复现方法

note 可以从更为本质的方案出发&#xff0c;通过分析强化学习的方法&#xff0c;看看如何实现o1&#xff0c;但其中的核心就是在于&#xff0c;如何有效地初始化策略、设计奖励函数、实现高效的搜索算法以及利用强化学习进行学习和优化。 文章目录 note一、Imitate, Explore, …...

与“神”对话:Swift 语言在 2025 中的云霓之望

0. 引子 夜深人静&#xff0c;是一片极度沉醉的黑&#xff0c;这便于我与深沉的 macbook 悄悄隐秘于其中。一股异香袭来&#xff0c;恍惚着&#xff0c;撸码中身心极度疲惫、头脑昏沉的我仿佛感觉到了一束淡淡的微光轻洒在窗边。 我的对面若隐若现逐渐浮现出一个熟悉的身影。他…...