【Apache POI】判断非空单元格

首先

使用Apache POI库读取Excel时,我想跳过具有删除线或隐藏的单元格,并查找了解了一种方法。下面是我作为个人备忘录记录下来的内容,如果觉得有帮助就请参考。
※基本的Apache POI写法将被省略。

目录

    1. 不显示的行

 

    1. 判断不显示的行

 

    1. 判断不显示的列

取消线

整个单元格有取消线
单元格内的部分有取消线

1. 不展示身份证明

コメント 2020-07-30 222355.png

1. 判断非表示行

我将进行判断,看这一行是否被隐藏起来了。

for(Row row : sheet){
   // 行が非表示か判定
   if(row.getZeroHeight()){
      // 非表示の場合、次の行を読み込む
      continue;
   }
   ...
}

2. 判断隐藏列

我们要判断列是否被隐藏。
在Apache POI中,我们是按照工作簿➡️工作表➡️行➡️列的顺序进行读取的,
因此针对列,我们需要以单元格为单位进行判断。
另外,由于单元格类中没有隐藏判断,因此需要在工作表类中编写判断处理。

for(Cell cell : row){
   // 列が非表示か判定
   if(sheet.isColumnHidden(cell.getColumnIndex())){
      // 非表示の場合、次のセルを読み込む
      continue;
   }
   ...
}

※这个处理在每个单元格中都要进行判断,但是如果读取大量的数据文件或多个文件一次性加载时,处理会变得非常慢。如果要处理大量的数据,可以将列号保持在列表中会更好。

取消线 – qǔ xīàn

image.png

1. 整格中的格子有一条删除线。

这是判断单元格是否有删除线的方法。

for(Cell cell : row){
   // セルのフォントを取得
   CellStyle style = c.getCellStyle();
   Font font = c.getSheet().getWorkbook().getFontAt(style.getFontIndex());
   // セルに取消線があるかどうかを判定
   if(font.getStrikeout()){
      // 取消線がある場合、次のセルを読み込む
      continue;
   }
   ...
}

2. 细胞内部有一部分有删除线。

如果单元格的一部分有删除线,则需要根据读取的Excel文件扩展名的类型来选择使用的写法。
※有关HSSF和XSSF的详细信息,请参阅此处。

如果文件的扩展名是xlsx的话

获取已划掉的字符串。
例)あいうえお → うえ

// XSSFRichTextString形式にてセルの値を取得
XSSFRichTextString richStr = (XSSFRichTextString) cell.getRichStringCellValue();
// セル内の文字列に当たっているフォントの塊の数を取得
int cnt = richStr.numFormattingRuns();
// フォントが当たっていないときは0になる
if (cnt == 0 ) {
   continue;
}
for (int i = 0; i < cnt; i++;) {
   // インデックスがi番目のフォントの塊を取得
   XSSFFont xssfFont = richStr.getFontOfFormattingRun(i);
   // 塊にフォントが当たっていなかった場合
   if (xssfFont == null) {
       continue;
   }
   // 塊にフォントが当たっていた場合、取消線があるかどうかの判定
   if (xssfFont.getStrikeout()) {
   // 取り消し線がある場合、i番目のインデックスの塊の文字列を取得
       System.out.println(richStr.getCTRst().getRArray(i).getT());
   }
}

上述的情况下,对于xlsx文件,可以相对简单地获取。我自己对于FormattingRun系列的处理意义有些困惑,但根据处理的结果看,似乎是将“あいうえお”按照“あい”、“うえ”和“お”的块进行分割(只是“あい”没有字体,“うえ”和“お”的获取涉及到文字大小、字体(如メイリオ)以及是否有删除线等)。

如果文件的扩展名是xls(Excel 97-2003版本)。

由于HSSFFont的类型较旧的版本,可能无法像XSSF那样直接获取字体本身,而只能获取带有删除线属性的索引。

String cellStr = cell.getStringCellValue();
HSSFRichTextString richStr = (HSSFRichTextString)cell.getRichStringCellValue();
// フォントが当たっている塊の数を取得
int cnt = richStr.numFormattingRuns();
if (cnt == 0){
   continue;
} else {
   int startStrikeoutIndex = -1;
   boolean isStrikeoutStartIndex = false;
   for (int i = 0; i < cnt; i++;) {
      // インデックスがi番目のフォントの塊を取得
      Font hssfFont = wb.getFontAt(richStr.getFontOfFormattingRun(i));
      int index = richStr.getIndexOfFormattingRun(i);
      // 塊にフォントが当たっていなかった場合
      if (hssfFont == null) {
          if (isStrikeoutStartIndex) {
             System.out.println(cellStr.substring(startStrikeoutIndex, index));
             isStrikeoutStartIndex = false;
          }
          continue;
      }
      // フォント設定はあるが取り消し線がない場合
      if (!hssfFont.getStrikeout()) {
          if (isStrikeoutStartIndex) {
             System.out.println(cellStr.substring(startStrikeoutIndex, index));
             isStrikeoutStartIndex = false; 
          }
      } 
      // 一部に取り消し線がある場合
      else if (hssfFont.getStrikeout()) {
          startStrikeoutIndex = index;
          isStrikeoutStartIndex = true;
          if (i + 1 == cnt) {
             // 最後の塊の場合はここで出力する。
             System.out.println(cellStr.substring(startStrikeoutIndex, cellStr.length()));
          }
      }
   }
}

根据我调查的内容,我使用了可用的处理方法进行实现,结果变得非常笨拙。简单来解释一下原理,以“あいうえお”为例,取得带有删除线的部分的第一个字符的索引作为“startStrikeoutIndex”(例如,当为“い”时索引为1),并将“isStrikeoutStartIndex”设为true。然后,如果“isStrikeoutStartIndex”为true,那么在“startStrikeoutIndex”和该块的下一个块的第一个字符索引(例如,对于“う”部分,索引为2)之间的字符将成为被删除线划掉的文字,因此我们取得该部分内容。

最后

因为这是一个相当艰苦的部分,所以我整理了一份可以在需要时回顾的资料。如果能对有同样想法的人有所帮助,那将更加令我高兴。

请在中文中提供一个这个句子的同义表达。

    Excelシート内の「取り消し線(打ち消し線)」設定の判定の仕方
广告
将在 10 秒后关闭
bannerAds