欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java導(dǎo)出Execl疑難點(diǎn)處理的實(shí)現(xiàn)

 更新時間:2020年04月17日 09:48:09   作者:盲目的拾荒者  
這篇文章主要介紹了Java導(dǎo)出Execl疑難點(diǎn)處理的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一.背景

最近業(yè)務(wù)需求需要導(dǎo)出Execl,最終做出的效果如下,中間牽扯到大量的數(shù)據(jù)計算。

二.疑難問題分析

問題1:跨單元格處理及邊框設(shè)置
問題2:自定義背景顏色添加
問題3:單元格中部分文字設(shè)置顏色
問題4:高度自適應(yīng)處理

三.問題解決

在處理整個Excel導(dǎo)出中總結(jié)了很多。

整個開發(fā)過程使用的是Apache POI

pom.xml

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

3.1 HSSFworkbook,XSSFworkbook選哪個

最開始我沿用的是之前開發(fā)用的,HSSFworkbook最后發(fā)現(xiàn),HSSFworkbook在處理,自定義單元格背景顏色比較復(fù)雜,最后換成了XSSFworkbook。

HSSFWorkbook:是操作Excel2003以前(包括2003)的版本,擴(kuò)展名是.xls;

XSSFWorkbook:是操作Excel2007后的版本,擴(kuò)展名是.xlsx;

所以在這里我推薦使用XSSFWorkbook

3.2跨單元格及邊框設(shè)置

//創(chuàng)建第一行,索引是從0開始的
row = sheet.createRow(0);
//創(chuàng)建第一個單元格
XSSFCell cell0 = row.createCell(0);
//設(shè)置單元格文字
cell0.setCellValue("姓名");
//設(shè)置單元格樣式
cell0.setCellStyle(cellStyleHead);
//跨單元格設(shè)置
//參數(shù)為 firstRow, lastRow, firstCol, lastCol
CellRangeAddress cellRange1 = new CellRangeAddress(0, 1, 0, 0);
sheet.addMergedRegion(cellRange1);
//注意如果直接在下面寫設(shè)置邊框的樣式,可能會出現(xiàn)邊框覆蓋不全的情況,可能是樣式覆蓋問題
//所以應(yīng)該在數(shù)據(jù)渲染完成之后,在代碼的最后寫跨單元格邊框設(shè)置,這是非常重要的

調(diào)用設(shè)置邊框

//在數(shù)據(jù)渲染完成,調(diào)用封裝的邊框設(shè)置方法
setRegionStyle(wb, sheet, cellRange1);

設(shè)置邊框方法

 /**
   * 合并單元格之后設(shè)置邊框
   *
   * @param wb   XSSFWorkbook對象
   * @param sheet sheet
   * @param region region
   */
  static void setRegionStyle(XSSFWorkbook wb, XSSFSheet sheet, CellRangeAddress region) {
    RegionUtil.setBorderTop(1, region, sheet, wb);
    RegionUtil.setBorderBottom(1, region, sheet, wb);
    RegionUtil.setBorderLeft(1, region, sheet, wb);
    RegionUtil.setBorderRight(1, region, sheet, wb);
  }

3.3自定義背景顏色設(shè)置

因?yàn)閜oi自帶的顏色索引可能不滿足我們開發(fā)的需求,需要自定義樣色

 //創(chuàng)建單元格樣式
 XSSFCellStyle cellStyleContent = wb.createCellStyle();
//創(chuàng)建背景顏色 226, 239, 218 對應(yīng)的就是RGB顏色 紅綠藍(lán)
 cellStyleContent.setFillForegroundColor(new XSSFColor(new java.awt.Color(226, 239, 218)));
//填充m
 cellStyleContent.setFillPattern(CellStyle.SOLID_FOREGROUND);

3.4設(shè)置單元格中部分字體顏色

 XSSFRichTextString ts = new XSSFRichTextString("123456\r\n789");
 XSSFFont font2 = wb.createFont();
 //字體高度
font2.setFontHeightInPoints((short) 10);
// 字體
font2.setFontName("宋體");
//字體顏色
font2.setColor(HSSFColor.GREEN.index);
//那些字體要設(shè)置顏色,
//int startIndex 開始索引
//int endIndex 結(jié)束索引
// Font font 字體
ts.applyFont(5, ts.length(), font2);

3.5高度自適應(yīng)

封裝的工具類如下,需要在數(shù)據(jù)渲染完的每行,調(diào)用如下工具類

//高度自適應(yīng)
//XSSFRow row;
ExcelUtil.calcAndSetRowHeigt(row);
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Created by niugang on 2020/3/13/13:34
 */
public class ExcelUtil {


  private ExcelUtil() {
    throw new IllegalStateException("Utility class");
  }

  /**
   * 根據(jù)行內(nèi)容重新計算行高
   *
   * @param sourceRow sourceRow
   */
  public static void calcAndSetRowHeigt(XSSFRow sourceRow) {
    for (int cellIndex = sourceRow.getFirstCellNum(); cellIndex <= sourceRow.getPhysicalNumberOfCells(); cellIndex++) {
      //行高
      double maxHeight = sourceRow.getHeight();
      XSSFCell sourceCell = sourceRow.getCell(cellIndex);
      //單元格的內(nèi)容
      String cellContent = getCellContentAsString(sourceCell);
      if (null == cellContent || "".equals(cellContent)) {
        continue;
      }
      //單元格的寬高及單元格信息
      Map<String, Object> cellInfoMap = getCellInfo(sourceCell);
      Integer cellWidth = (Integer) cellInfoMap.get("width");
      Integer cellHeight = (Integer) cellInfoMap.get("height");
      if (cellHeight > maxHeight) {
        maxHeight = cellHeight;
      }
      XSSFCellStyle cellStyle = sourceCell.getCellStyle();
      //sourceRow.getSheet().getWorkbook()
      XSSFFont font = cellStyle.getFont();
      //字體的高度
      short fontHeight = font.getFontHeight();

      //cell內(nèi)容字符串總寬度
      double cellContentWidth = cellContent.getBytes().length * 2 * 256;

      //字符串需要的行數(shù) 不做四舍五入之類的操作
      double stringNeedsRows = cellContentWidth / cellWidth;
      //小于一行補(bǔ)足一行
      if (stringNeedsRows < 1.0) {
        stringNeedsRows = 1.0;
      }

      //需要的高度 			(Math.floor(stringNeedsRows) - 1) * 40 為兩行之間空白高度
      double stringNeedsHeight = (double) fontHeight * stringNeedsRows;
      //需要重設(shè)行高
      if (stringNeedsHeight > maxHeight) {
        maxHeight = stringNeedsHeight;
        //超過原行高三倍 則為5倍 實(shí)際應(yīng)用中可做參數(shù)配置
        if (maxHeight / cellHeight > 5) {
          maxHeight = 5 * cellHeight;
        }
        //最后取天花板防止高度不夠
        maxHeight = Math.ceil(maxHeight);
        //重新設(shè)置行高 同時處理多行合并單元格的情況
        Boolean isPartOfRowsRegion = (Boolean) cellInfoMap.get("isPartOfRowsRegion");
        if (isPartOfRowsRegion.equals(Boolean.TRUE)) {
          Integer firstRow = (Integer) cellInfoMap.get("firstRow");
          Integer lastRow = (Integer) cellInfoMap.get("lastRow");
          //平均每行需要增加的行高
          double addHeight = (maxHeight - cellHeight) / (lastRow - firstRow + 1);
          for (int i = firstRow; i <= lastRow; i++) {
            double rowsRegionHeight = sourceRow.getSheet().getRow(i).getHeight() + addHeight;
            rowsRegionHeight=rowsRegionHeight+10;
            sourceRow.getSheet().getRow(i).setHeight((short) rowsRegionHeight);
          }
        } else {
          maxHeight=maxHeight+10;
          sourceRow.setHeight((short) maxHeight);
        }
      }

    }
  }

  /**
   * 解析一個單元格得到數(shù)據(jù)
   *
   * @param cell cell
   * @return String
   */
  private static String getCellContentAsString(XSSFCell cell) {
    final String strZero =".0";
    if (null == cell) {
      return "";
    }
    String result = "";
    switch (cell.getCellType()) {
      case Cell.CELL_TYPE_NUMERIC:
        String s = String.valueOf(cell.getNumericCellValue());
        if (s != null) {
          if (s.endsWith(strZero)) {
            s = s.substring(0, s.length() - 2);
          }
        }
        result = s;
        break;
      case Cell.CELL_TYPE_STRING:
        result = String.valueOf(cell.getStringCellValue()).trim();
        break;
      case Cell.CELL_TYPE_BLANK:
        break;
      case Cell.CELL_TYPE_BOOLEAN:
        result = String.valueOf(cell.getBooleanCellValue());
        break;
      case Cell.CELL_TYPE_ERROR:
        break;
      default:
        break;
    }
    return result;
  }

  /**
   * 獲取單元格及合并單元格的寬度
   *
   * @param cell cell
   * @return Map<String  ,    Object>
   */
  private static Map<String, Object> getCellInfo(XSSFCell cell) {
    XSSFSheet sheet = cell.getSheet();
    int rowIndex = cell.getRowIndex();
    int columnIndex = cell.getColumnIndex();

    boolean isPartOfRegion = false;
    int firstColumn = 0;
    int lastColumn = 0;
    int firstRow = 0;
    int lastRow = 0;
    int sheetMergeCount = sheet.getNumMergedRegions();
    for (int i = 0; i < sheetMergeCount; i++) {
      CellRangeAddress ca = sheet.getMergedRegion(i);
      firstColumn = ca.getFirstColumn();
      lastColumn = ca.getLastColumn();
      firstRow = ca.getFirstRow();
      lastRow = ca.getLastRow();
      if (rowIndex >= firstRow && rowIndex <= lastRow) {
        if (columnIndex >= firstColumn && columnIndex <= lastColumn) {
          isPartOfRegion = true;
          break;
        }
      }
    }
    Map<String, Object> map = new HashMap<>(16);
    int width = 0;
    int height = 0;
    boolean isPartOfRowsRegion = false;
    if (isPartOfRegion) {
      for (int i = firstColumn; i <= lastColumn; i++) {
        width += sheet.getColumnWidth(i);
      }
      for (int i = firstRow; i <= lastRow; i++) {
        height += sheet.getRow(i).getHeight();
      }
      if (lastRow > firstRow) {
        isPartOfRowsRegion = true;
      }
    } else {
      width = sheet.getColumnWidth(columnIndex);
      height += cell.getRow().getHeight();
    }
    map.put("isPartOfRowsRegion", isPartOfRowsRegion);
    map.put("firstRow", firstRow);
    map.put("lastRow", lastRow);
    map.put("width", width);
    map.put("height", height);
    return map;
  }
}

到此這篇關(guān)于Java導(dǎo)出Execl疑難點(diǎn)處理的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java導(dǎo)出Execl內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java異常處理的12條軍規(guī)總結(jié)

    Java異常處理的12條軍規(guī)總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java異常處理的12條軍規(guī),文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • HTTP中g(shù)et和post的區(qū)別詳解

    HTTP中g(shù)et和post的區(qū)別詳解

    這篇文章主要為大家詳細(xì)介紹了HTTP中g(shù)et和post的區(qū)別,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • mybatis?使用concat?模糊查詢方式

    mybatis?使用concat?模糊查詢方式

    這篇文章主要介紹了mybatis?使用concat?模糊查詢方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Spring中的refreshContext源碼分析

    Spring中的refreshContext源碼分析

    這篇文章主要介紹了Spring中的refreshContext源碼分析,在SpringBoot啟動流程中,主要的兩個階段是初始化SpringApplication對象以及SpringApplication.run方法執(zhí)行的內(nèi)容,今天主要細(xì)講的是SpringApplication.run中的刷新容器refreshContext方法,需要的朋友可以參考下
    2023-12-12
  • Java中List集合的常用方法詳解

    Java中List集合的常用方法詳解

    本篇文章給大家?guī)淼膬?nèi)容是關(guān)于Java中List集合的常用方法詳解,有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。下面我們就來學(xué)習(xí)一下吧
    2021-11-11
  • springboot 項(xiàng)目容器啟動后如何自動執(zhí)行指定方法

    springboot 項(xiàng)目容器啟動后如何自動執(zhí)行指定方法

    這篇文章主要介紹了springboot 項(xiàng)目容器啟動后如何自動執(zhí)行指定方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Struts攔截器實(shí)現(xiàn)攔截未登陸用戶實(shí)例解析

    Struts攔截器實(shí)現(xiàn)攔截未登陸用戶實(shí)例解析

    這篇文章主要介紹了Struts攔截器實(shí)現(xiàn)攔截未登陸用戶實(shí)例解析,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • Java遞歸實(shí)現(xiàn)評論多級回復(fù)功能

    Java遞歸實(shí)現(xiàn)評論多級回復(fù)功能

    這篇文章主要介紹了Java遞歸實(shí)現(xiàn)評論多級回復(fù)功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • 關(guān)于Spring Bean實(shí)例過程中使用反射和遞歸處理的Bean屬性填充問題

    關(guān)于Spring Bean實(shí)例過程中使用反射和遞歸處理的Bean屬性填充問題

    本文帶領(lǐng)大家一起學(xué)習(xí)下在Spring Bean實(shí)例過程中如何使用反射和遞歸處理的Bean屬性填充,需要在類 AbstractAutowireCapableBeanFactory 的 createBean 方法中添加補(bǔ)全屬性方法,具體操作方法跟隨小編一起學(xué)習(xí)下吧
    2021-06-06
  • MyBatis實(shí)現(xiàn)動態(tài)SQL的方法

    MyBatis實(shí)現(xiàn)動態(tài)SQL的方法

    動態(tài)SQL是MyBatis強(qiáng)大特性之一,極大的簡化我們拼裝SQL的操作,本文主要介紹了MyBatis實(shí)現(xiàn)動態(tài)SQL的方法,具有一定的參考價值,感興趣的可以了解一下
    2024-06-06

最新評論