当前位置: 首页 > 知识库问答 >
问题:

Apache POI无法检测哈希格式的数字

商飞翮
2023-03-14

我需要将通过XLS/XLSX上传的电话号码读入Java字符串变量,尽可能接近excel文件中显示的内容。

正如您所看到的,单元格中的实际值是166609999,其格式为60#########################/code>,所以最后我们会看到60166609999出现在单元格上。

我想以60166609999的字符串形式捕获单元格内容,但到目前为止,我只捕获了166609999,有人能告诉我有什么问题吗?

注意:如果将格式从60##############更改为60000000000,我可以毫无问题地捕获60166609999,但excel是通过公共站点上载的,因此无法强制执行。

代码简单到:

Cell cell = getTheCell(); // Got this after reading the sheets and rows
DataFormatter df = new DataFormatter();
String value = df.formatCellValue(cell);
// Here in value
// If format is 600000000, I can get 60166609999 (right)
// If format is 60#######, I get 166609999 (wrong)

我正在使用的库:

    null

共有1个答案

元胡媚
2023-03-14

问题是多维的。

起初,数字格式60#############不能应用usigJava。它导致java.lang.IllegalArgumentException:使用DecimalFormat的格式错误的模式“60################”

但是,如果需要每个数字前缀为“60”,那么Excel数字格式\6\0#“60”#应该是可能的,并且应该转换为DecimalFormat模式'60'#。但是Apache POIDataFormatter不会这样做,因为它只是从Excel的格式字符串中删除所有引号,从而导致60#也是格式错误的模式。

...
        // Now, handle the other aspects like 
        //  quoting and scientific notation
        for(int i = 0; i < sb.length(); i++) {
           char c = sb.charAt(i);
/*
            // remove quotes and back slashes
            if (c == '\\' || c == '"') {
                sb.deleteCharAt(i);
                i--;
*/
            // handle quotes and back slashes
            if (c == '\\') {
                sb.setCharAt(i, '\'');
                sb.insert(i+2, '\'');
                i+=2;
            } else if (c == '"') {
                sb.setCharAt(i, '\'');
            // for scientific/engineering notation
            } else if (c == '+' && i > 0 && sb.charAt(i - 1) == 'E') {
                sb.deleteCharAt(i);
                i--;
            }
        }

        formatStr = sb.toString();
        formatStr = formatStr.replace("''", ""); 
        return formatStr;
    }
...

在本例中使用以下内容:

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;

import java.io.FileInputStream;

import java.lang.reflect.Method;

class ExcelDataformatterExample {

 public static void main(String[] args) throws Exception {

  Workbook wb  = WorkbookFactory.create(new FileInputStream("ExcelExample.xlsx"));

  DataFormatter df = new DataFormatter();
  MyDataFormatter mydf = new MyDataFormatter();

  Sheet sheet = wb.getSheetAt(0);
  for (Row row : sheet) {
   for (Cell cell : row) {
    if (cell.getCellTypeEnum() == CellType.NUMERIC) {
     CellReference cellRef = new CellReference(row.getRowNum(), cell.getColumnIndex());
     System.out.println("Cell " + cellRef.formatAsString());

     System.out.print("Excel's data format string: ");
     String formatStr = cell.getCellStyle().getDataFormatString();
     System.out.println(formatStr);

     System.out.print("Value using poi's data formatter: ");
     Method cleanFormatForNumber = DataFormatter.class.getDeclaredMethod("cleanFormatForNumber", String.class); 
     cleanFormatForNumber.setAccessible(true); 
     String cleanFormatStr = (String)cleanFormatForNumber.invoke(df, formatStr);
     System.out.print("using poi's cleanFormatStr: ");
     System.out.print(cleanFormatStr + " result: ");
     String value = df.formatCellValue(cell);
     System.out.println(value);

     System.out.print("Value using my data formatter: ");
     cleanFormatForNumber = MyDataFormatter.class.getDeclaredMethod("cleanFormatForNumber", String.class); 
     cleanFormatForNumber.setAccessible(true); 
     cleanFormatStr = (String)cleanFormatForNumber.invoke(mydf, formatStr);
     System.out.print("using my cleanFormatStr: ");
     System.out.print(cleanFormatStr + " result: ");
     value = mydf.formatCellValue(cell);
     System.out.println(value);

    }
   }
  }
  wb.close();

 }

}

如果值199901234位于A1A4Excel中格式化的单元格中,则会导致如下输出:

Cell A1
Excel's data format string: \60##########
Value using poi's data formatter: using poi's cleanFormatStr: 60########## result: 199901234
Value using my data formatter: using my cleanFormatStr: '6'0########## result: 199901234
Cell A2
Excel's data format string: \60000000000
Value using poi's data formatter: using poi's cleanFormatStr: 60000000000 result: 60199901234
Value using my data formatter: using my cleanFormatStr: '6'0000000000 result: 60199901234
Cell A3
Excel's data format string: "60"#
Value using poi's data formatter: using poi's cleanFormatStr: 60# result: 199901234
Value using my data formatter: using my cleanFormatStr: '60'# result: 60199901234
Cell A4
Excel's data format string: \6\0#
Value using poi's data formatter: using poi's cleanFormatStr: 60# result: 199901234
Value using my data formatter: using my cleanFormatStr: '60'# result: 60199901234
 类似资料:
  • 所以,我有一个带有数组的哈希,就像这样: 我想将它们合并到一个哈希数组中,组合相应的元素。 结果应该是这样的: 知道如何有效地做到这一点吗? 请注意,真实世界的使用场景可能包含数量可变的散列键。

  • 循环在具有特定键值对的文本文件上运行三次。每个循环都会返回一个新的散列,如下所示。我想将这些散列存储到另一个散列中。,和是散列的关键: 我将上述散列初始化为而不是我想将它们存储到散列中。我想初始化更大的散列,比如。 但它只给了我

  • 问题内容: 基本类型(例如int)的哈希码是什么? 例如,假设num是一个整数。 问题答案: 对于一个最自然的选择是使用本身。一个更好的问题是,用什么的的,因为它不适合的尺度的哈希码。您的最佳解决方案以及所有相关问题将是有效的Java。

  • 问题内容: 我正在尝试使用C#处理一些json格式的数据,但是在确定解决该问题的正确方法时遇到了一些问题。我的问题是json格式的数据将采用未知格式(我知道听起来很奇怪,请继续阅读)。基本上,json格式的数据将是名称/值对的一些集合,其中值可能是也可能不是嵌套的名称/值对的数组。为了使事情变得更加有趣,名称/值对数组的嵌套可以在无限时继续进行。 例如:我可能有一些看起来像……的数据。 不幸的是,

  • 问题内容: 我只是在http://ritter.vg上设置了新主页。我正在使用jQuery,但是使用的次数很少。 它使用AJAX加载所有页面-我将其设置为通过检测URL中的哈希来允许添加书签。 但是我无法使用后退和前进按钮。 有没有一种方法可以在不使用setInterval循环的情况下检测何时按下后退按钮(或检测哈希值何时变化)?当我尝试使用.2和1秒超时的那些时,它挂住了我的CPU。 问题答案:

  • 考虑@data是一个带有日期、类、名称和等级字段的Active记录数组。假设我想以两个哈希结束,一个是每个名称的所有日期的唯一集合;另一个按类、日期和名称细分以显示等级。 > 导致错误: nil:NilClass的未定义方法“[]=”