1. POIの紹介
詳細については、この記事を参照してください
https://blog.csdn.net/w893932747/article/details/89354979
2. POI実装エクスポート例
springboot プロジェクトで Excel ファイルをエクスポートするために poi を統合するインターフェイスの例を書いてみましょう
1. 環境の準備
最初に springboot プロジェクトを準備します。ここでは例は示しません
。 springboot プロジェクトの下に poi の依存関係を導入します。例として 3.17 バージョンを示します。
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
データの準備として、次のデータをレポート
データ レポート SQL ファイルとしてエクスポートします:
https://pan.baidu.com/s/1bv0EV1fIhbExD6j0dhlzPw 抽出コード 8qz1
2. Daoレイヤーを作成する
- エンティティクラス
public class GoodInfo {
private Long spuId;
private String title;
private String cname;
private String brandName;
private String skuId;
private String subTitle;
private String ownSpec;
private Double price;
/*Getter Setter自行添加*/
- Daoクラス(ここではクエリSQLをアノテーション形式で記述しています)
import com.changgou.item.po.GoodInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface PoiDao {
@Select("SELECT * FROM `good_info` ORDER BY spu_id LIMIT 200")
List<GoodInfo> getGoodInfo();
}
2. コントローラー層を作成する
import com.changgou.item.service.PoiService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("poi")
public class PoiController {
@Autowired
private PoiService poiService;
@PostMapping("/export")
public ResponseEntity<Void> exportGoodInfo(HttpServletResponse response) {
poiService.exportGoodInfo(response);
return ResponseEntity.ok().build();
}
}
3. サービス層の作成
データ レポート例の最初のいくつかのフィールドの値と最後のいくつかのフィールドの値には 1 対多の関係があるため、各データのフロント部門のフィールドが同じであることがわかります。ここではそれらをグループ化します。この部分の同じフィールドごとにセルを配置し、同じ値の部門フィールドを持つセルを結合します。
import com.alibaba.fastjson.JSONObject;
import com.changgou.item.dao.PoiDao;
import com.changgou.item.po.GoodInfo;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class PoiService {
private final Logger LOGGER = LoggerFactory.getLogger(this.getClass());
public static final List<String> GOOD_INFO_COLUMNS = new ArrayList<>(
Arrays.asList("spu编号", "标题","商品分类","商品品牌","sku编号","详细信息","参数属性","价格")
);
public static final List<String> GOOD_COLUMNS = new ArrayList<>(
Arrays.asList("spuId", "title","cname","brandName","skuId","subTitle","ownSpec","price")
);
@Autowired
private PoiDao poiDao;
public void exportGoodInfo(HttpServletResponse response) {
List<GoodInfo> goodInfoList = poiDao.getGoodInfo();
// 按spuId分组
Map<String, List<GoodInfo>> goodInfoMap = goodInfoList.stream()
.collect(Collectors.groupingBy(item -> item.getSpuId().toString()));
// 创建一个空的excel表格
HSSFWorkbook workbook = new HSSFWorkbook();
// 创建一个sheet页
HSSFSheet sheet = workbook.createSheet("商品信息列表");
// 创建表头
HSSFRow row = sheet.createRow(0);
// 创建表头格式style对象
HSSFCellStyle style = workbook.createCellStyle();
// 创建字体对象
HSSFFont font = workbook.createFont();
//字体设置为红色
font.setColor(IndexedColors.RED.index);
//字体加粗
font.setBold(true);
style.setFont(font);
// 设置单元格水平居中
style.setAlignment(HorizontalAlignment.CENTER);
// 设置单元格填充色
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
style.setFillForegroundColor(IndexedColors.YELLOW.index);
Map<Integer, Integer> columnWidthMap = new HashMap<>();
// 写入表头
for (int i = 0; i< GOOD_INFO_COLUMNS.size(); i++) {
// 创建单元格
HSSFCell cell = row.createCell(i);
cell.setCellStyle(style);
// 设置单元格宽度
sheet.setColumnWidth(i, GOOD_INFO_COLUMNS.get(i).getBytes().length *256);
// 将表头值字符长度保存到columnWidthMap中
columnWidthMap.put(i, GOOD_INFO_COLUMNS.get(i).getBytes().length);
// 设置表有值
cell.setCellValue(GOOD_INFO_COLUMNS.get(i));
}
// 记录正文行号
int page = 1;
// 创建正文格式style对象
style = workbook.createCellStyle();
style.setAlignment(HorizontalAlignment.CENTER);
// 遍历正文数据
for (Map.Entry<String, List<GoodInfo>> entry : goodInfoMap.entrySet()) {
// 记录每组数据起始行数
int firstRow = page;
for (GoodInfo goodInfo : entry.getValue()) {
// 创建正文行
HSSFRow goodRow = sheet.createRow(page);
Map<String, Object> map = JSONObject.parseObject(JSONObject.toJSONString(goodInfo), Map.class);
for (int i = 0; i< GOOD_COLUMNS.size(); i++) {
// 创建单元格
HSSFCell cell = goodRow.createCell(i);
cell.setCellStyle(style);
Object object = map.get(GOOD_COLUMNS.get(i));
String value = object == null ? "" : object.toString();
// 设置单元格狂歌为字段值最大的宽度
int headerLength = columnWidthMap.get(i);
int valueLength = value.getBytes().length;
int columnWidth = headerLength > valueLength ? headerLength : valueLength;
columnWidthMap.put(i, columnWidth);
sheet.setColumnWidth(i, columnWidth * 256);
cell.setCellValue(value);
}
page++;
}
// 记录每组数据末尾行数
int lastRow = firstRow + entry.getValue().size() - 1;
// 合并相同字段的单元格
if (firstRow < lastRow) {
for (int j = 0; j < 4; j++) {
CellRangeAddress region = new CellRangeAddress(firstRow, lastRow, j, j);
sheet.addMergedRegion(region);
}
}
}
response.setContentType("application/vnd.ms-excel");
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String fileName = new String(("goodInfoList" + sdf.format(new Date()) + ".xls"));
try {
OutputStream os = response.getOutputStream();
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
workbook.write(os);
} catch (Exception e) {
LOGGER.error("fail: ", e);
}
}
}
4. 最終的なエフェクト表示
次の操作が完了したら、プロジェクトを開始してインターフェイスを呼び出すことができ、最終的なレポート ファイルは次のように表示されます。