为什么JExcel在分配的货币符号(£)上强制使用单元格的正前缀($)?

我有一个使用JExcel库读取Excel表格的程序,并对它们进行一些处理。

我曾经注意到的一件令人不安的事情是(被我们的一个用户通知)是JExcel似乎是强制转换单元格形成货币单元格来使用$符号。 我已经做了很多挖掘,但我不知道下一步该去哪里。 跳到底部看问题的症结所在。

实质上,我们有这个方法:

import java.io.File; import java.io.IOException; import java.util.Locale; import jxl.Cell; import jxl.Sheet; import jxl.Workbook; import jxl.WorkbookSettings; import jxl.read.biff.BiffException; public class Launcher { /** * @param args */ public static void main(String[] args) { nothingSpecifc("D:\\Documents and Settings\\castone\\My Documents\\JExcelCurrencyExample.xls"); } public static void nothingSpecifc(String excelFilePath){ try { File myFile = new File(excelFilePath); Locale myLocal = Locale.UK; WorkbookSettings wbkSettings = new WorkbookSettings(); wbkSettings.setLocale(myLocal); wbkSettings.setEncoding("UTF-8"); wbkSettings.setExcelDisplayLanguage("UK"); Workbook workbook = Workbook.getWorkbook(myFile,wbkSettings); Sheet mySheet = workbook.getSheet(0); Cell[] myRow = mySheet.getRow(0); String myCellA1 = myRow[0].getContents(); System.out.println(myCellA1); } catch (BiffException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } 

我的例子.xls文件在A1中有这个值:

excel文件的屏幕快照,打开格式化窗口

但运行后,我得到这个价值!

Eclipse的屏幕截图,输出格式不正确

现在我无法理解为什么会发生这种情况。 令人不安的是,我担心我所做的任何修正都会迫使其他货币符号转换为英镑符号。

看着Workbook.java,我打电话给这个方法:

  /** * A factory method which takes in an excel file and reads in the contents. * * @exception IOException * @exception BiffException * @param file the excel 97 spreadsheet to parse * @param ws the settings for the workbook * @return a workbook instance */ public static Workbook getWorkbook(java.io.File file, WorkbookSettings ws) throws IOException, BiffException { FileInputStream fis = new FileInputStream(file); // Always close down the input stream, regardless of whether or not the // file can be parsed. Thanks to Steve Hahn for this File dataFile = null; try { dataFile = new File(fis, ws); } catch (IOException e) { fis.close(); throw e; } catch (BiffException e) { fis.close(); throw e; } fis.close(); Workbook workbook = new WorkbookParser(dataFile, ws); workbook.parse(); return workbook; } 

所以实质上,这个类只是文件I / O处理和excel之间的一个聪明的包装器/接口。 我正在研究WorkbookSettings和WorkbookParser的默认构造函数。

首先,WorkbookSettings:

  /** * Default constructor */ public WorkbookSettings() { initialFileSize = DEFAULT_INITIAL_FILE_SIZE; arrayGrowSize = DEFAULT_ARRAY_GROW_SIZE; localeFunctionNames = new HashMap(); excelDisplayLanguage = CountryCode.USA.getCode(); excelRegionalSettings = CountryCode.UK.getCode(); refreshAll = false; template = false; excel9file = false; windowProtected = false; hideobj = HIDEOBJ_SHOW_ALL; // Initialize other properties from the system properties try { boolean suppressWarnings = Boolean.getBoolean("jxl.nowarnings"); setSuppressWarnings(suppressWarnings); drawingsDisabled = Boolean.getBoolean("jxl.nodrawings"); namesDisabled = Boolean.getBoolean("jxl.nonames"); gcDisabled = Boolean.getBoolean("jxl.nogc"); rationalizationDisabled = Boolean.getBoolean("jxl.norat"); mergedCellCheckingDisabled = Boolean.getBoolean("jxl.nomergedcellchecks"); formulaReferenceAdjustDisabled = Boolean.getBoolean("jxl.noformulaadjust"); propertySetsDisabled = Boolean.getBoolean("jxl.nopropertysets"); ignoreBlankCells = Boolean.getBoolean("jxl.ignoreblanks"); cellValidationDisabled = Boolean.getBoolean("jxl.nocellvalidation"); autoFilterDisabled = !Boolean.getBoolean("jxl.autofilter"); // autofilter currently disabled by default useTemporaryFileDuringWrite = Boolean.getBoolean("jxl.usetemporaryfileduringwrite"); String tempdir = System.getProperty("jxl.temporaryfileduringwritedirectory"); if (tempdir != null) { temporaryFileDuringWriteDirectory = new File(tempdir); } encoding = System.getProperty("file.encoding"); } catch (SecurityException e) { logger.warn("Error accessing system properties.", e); } // Initialize the locale to the system locale try { if (System.getProperty("jxl.lang") == null || System.getProperty("jxl.country") == null) { locale = Locale.getDefault(); } else { locale = new Locale(System.getProperty("jxl.lang"), System.getProperty("jxl.country")); } if (System.getProperty("jxl.encoding") != null) { encoding = System.getProperty("jxl.encoding"); } } catch (SecurityException e) { logger.warn("Error accessing system properties.", e); locale = Locale.getDefault(); } } 

这里什么都没有,我已经把Encoding,Local和DisplayLanguage设置为英国的特定/兼容的。 区域设置默认情况下已经是英国。

现在为WorkbookParser:

 public class WorkbookParser extends Workbook implements ExternalSheet, WorkbookMethods { /** * The logger */ private static Logger logger = Logger.getLogger(WorkbookParser.class); /** * The excel file */ private File excelFile; /** * The number of open bofs */ private int bofs; /** * Indicates whether or not the dates are based around the 1904 date system */ private boolean nineteenFour; /** * The shared string table */ private SSTRecord sharedStrings; /** * The names of all the worksheets */ private ArrayList boundsheets; /** * The xf records */ private FormattingRecords formattingRecords; /** * The fonts used by this workbook */ private Fonts fonts; /** * The sheets contained in this workbook */ private ArrayList sheets; /** * The last sheet accessed */ private SheetImpl lastSheet; /** * The index of the last sheet retrieved */ private int lastSheetIndex; /** * The named records found in this workbook */ private HashMap namedRecords; /** * The list of named records */ private ArrayList nameTable; /** * The list of add in functions */ private ArrayList addInFunctions; /** * The external sheet record. Used by formulas, and names */ private ExternalSheetRecord externSheet; /** * The list of supporting workbooks - used by formulas */ private ArrayList supbooks; /** * The bof record for this workbook */ private BOFRecord workbookBof; /** * The Mso Drawing Group record for this workbook */ private MsoDrawingGroupRecord msoDrawingGroup; /** * The property set record associated with this workbook */ private ButtonPropertySetRecord buttonPropertySet; /** * Workbook protected flag */ private boolean wbProtected; /** * Contains macros flag */ private boolean containsMacros; /** * The workbook settings */ private WorkbookSettings settings; /** * The drawings contained in this workbook */ private DrawingGroup drawingGroup; /** * The country record (containing the language and regional settings) * for this workbook */ private CountryRecord countryRecord; private ArrayList xctRecords; /** * Constructs this object from the raw excel data * * @param f the excel 97 biff file * @param s the workbook settings */ public WorkbookParser(File f, WorkbookSettings s) { super(); excelFile = f; boundsheets = new ArrayList(10); fonts = new Fonts(); formattingRecords = new FormattingRecords(fonts); sheets = new ArrayList(10); supbooks = new ArrayList(10); namedRecords = new HashMap(); lastSheetIndex = -1; wbProtected = false; containsMacros = false; settings = s; xctRecords = new ArrayList(10); } 

在这里我看不到任何会影响工作簿创build/访问的内容。


往下看,通过床单和细胞,我发现了两件有趣的事情:

  1. 单元格的格式有这个参数| positivePrefix|"$" (id=709)
  2. 这个货币正确的。 看这个:
    变量形成eclipse调试窗口,显示货币为GBP /£

所以我的问题是,当一个单元格运行getContents()方法时,为什么它不返回货币(给予,我想£$ ##### ,因为它仍然有postivePrefix),为什么正面这个前缀被设置为$吗?

我看不到在src文档中创build单元格的位置,或者getContents()方法实现的位置(我发现它是声明),所以我无法进一步挖掘,但是我希望别人知道这个“问题“,或者至less是一个工作?

这是为我做的。 进行一些设置。 以WorkbookSettings作为第二个参数获取工作簿。 我认为编码对你是重要的。

  WorkbookSettings wbs = new WorkbookSettings(); wbs.setExcelRegionalSettings("GB"); wbs.setExcelDisplayLanguage("GB"); Locale l = new Locale("en_GB"); wbs.setLocale(l); wbs.setEncoding("ISO8859_1"); Workbook workbook = Workbook.getWorkbook(new File("experimental-in.xls"), wbs); 

我无法弄清楚为什么会发生这种情况。 但是,如果你无法修复系统,请破解!

我以下列forms之一获得回报,单元格的值为100:

  • 100 – 普通数字
  • [£$ -42] 100 – 无法识别前缀货币
  • 100 [£$ -42] – Postfix货币未被识别
  • "?" 100 "?" 100 – 前缀符号不可渲染
  • 100 "?" – 后缀符号不可渲染

所以我决定,我应该regex从什么cell.getContent()返回的数字,一旦我确定我有一个数字。


认识到数字格式:

 public static boolean isNumberFormat(Cell cell){ CellType myCellType = cell.getType(); return myCellType.equals(CellType.NUMBER); } 

用正则expression式捕获数字

我得到了正则expression式text2re的'风格',对于上面的每一个,然后用debuggex玩,直到我把它们组合起来。 这导致了以下regexexpression式:

 (?:\"..*?\"|\[.*?\])*?\s*(\d+,?\d*?\.\d*)\s*(?:\[..*?]|".*?")*? 

这看起来像一个噩梦,但我会打破它,如在我的代码:

String digits="(\\d+,?\\d?\\.\\d*)";

一个或多个数字,用逗号和小数点。

String sbraceGroup="\\[.*?\\]";

匹配方括号内的零个或多个字符的组

String quotationGroup="\"..*?\"";

匹配引号中包含零个或多个字符的组

String junk = "(?:"+sbraceGroup+"|"+quotationGroup+")*?";

正则expression式的东西,我们想要的string,使用(?:.....)作为一个不匹配的组合,并*? 对于一个非常规的零 – >很多匹配。

我现在可以编译我的模式:

Pattern p = Pattern.compile(junk+"\\s*"+digits+"\\s*"+junk,Pattern.CASE_INSENSITIVE | Pattern.DOTALL);

\s*是零 – >许多空白字符(制表符,空格等)。

现在一起:

 String myCellA1 = myRow[rowCounter].getContents(); String digits="(\\d+,?\\d?\\.\\d*)"; // Non-greedy match on digits String sbraceGroup="\\[.*?\\]"; // non-greedy match on square Braces 1 String quotationGroup="\"..*?\""; // non-greedy match on things in quotes String junk = "(?:"+sbraceGroup+"|"+quotationGroup+")*?"; Pattern p = Pattern.compile(junk+"\\s*"+digits+"\\s*"+junk,Pattern.CASE_INSENSITIVE | Pattern.DOTALL); Matcher m = p.matcher(myCellA1); String match = ""; if (m.find()) { match=m.group(1).toString(); }else { match = myCellA1; } 

现在我已经解决了我的问题