1

JExcel ライブラリを使用して Excel シートを読み込んで処理するプログラムがあります。

私が気になったのは、(ユーザーの 1 人から通知された後) 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);
  }

ワークブックの作成/アクセスに影響を与えるものはここにはありません。


シートとセルをさらに下に見ていくと、2 つの興味深いことがわかりました。

  1. セルのフォーマットには、このパラメーター |value がありますpositivePrefix|"$" (id=709)
  2. これの通貨正しいです。これを見てください:
    変数は eclipse デバッグ ウィンドウを形成し、通貨を GBP/£ として表示します。

したがって、私の質問は、getContents()メソッドがセルで実行されたときに、通貨で返されないのはなぜですか(まだ postivePrefix があるため、£$#####$を与えると思います)、なぜこの正のプレフィックスとにかくに設定されますか?

src ドキュメントでセルが作成された場所や getContents() メソッドが実装されている場所 (宣言であることがわかりました) がわからないので、これ以上掘り下げることはできませんが、他の誰かがこの原因を知っていることを望んでいました。問題」、または少なくとも回避策はありますか?.

4

2 に答える 2

2

これは私のためにそれをしました。いくつかの設定を行います。WorkbookSettings を 2 番目のパラメーターとして使用してブックを取得します。エンコーディングはあなたにとって重要なものだと思います。

    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);
于 2016-11-25T00:04:40.660 に答える
1

なぜこれが起こっているのかわかりません。ただし、システムを修正できない場合は、ハッキングしてください。

セルの「値」が 100 の場合、次のいずれかの形式で返されます。

  • 100- プレーン番号
  • [£$ -42] 100- プレフィックス通貨が認識されない
  • 100 [£$ -42]- 後置通貨が認識されない
  • "?" 100- プレフィックス シンボルはレンダリングできません
  • 100 "?"- Postfix Symbol はレンダリングできません

cell.getContent()そのため、数値があると判断したら、戻り値から数値を正規表現する必要があると判断しました。


数値形式の認識:

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

正規表現で数字をキャプチャする

上記のそれぞれについて、正規表現形式text2reの「スタイル」を取得し、それらを組み合わせるまでdebuggexで遊んだ。これにより、次のregex式が得られました。

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

これは悪夢のように見えますが、コードのように分解します。

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

コンマを含む 1 つ以上の数字と小数点以下の桁数。

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

角括弧で囲まれた 0 個以上の文字に一致するグループ

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

引用符で囲まれた 0 個以上の文字に一致するグループ

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

望ましくない正規表現の文字列で、(?:.....)一致しないグループとして囲むために使用さ*?れ、貪欲でないゼロ->多一致に使用されます。

パターンをコンパイルできるようになりました。

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;
}

そして今、私は自分の問題を解決しました

于 2013-04-09T10:48:38.613 に答える