しかし、最終ドキュメントのテンプレートからいくつかのページがあり、その逆の場合、他のページを数回「複製」して、異なるデータで埋めることができますか? そして、コードのマッピングタグ->値の退屈な充填を取り除く方法は?
ドキュメントのシートモデルについて説明しましょう。
public class SheetModel { private String sheetToClone; //, private String sheetName; // private Map<String, Object> mappings; //getters and setters }
次に、 Apache POIを使用して本に目を通し、sheetToCloneという名前のシートを見つけて、そのコピーを作成します。 したがって、SheetModelクラスのオブジェクトをいくつでも作成し、それらをループで調べて、最終的に元のドキュメントのシートとそのコピーを含むドキュメントを取得できます。 次に、「ソース」シートが削除されます。
private void createNewSheets(List<SheetModel> sheetModelList){ for (SheetModel sheetModel: sheetModelList){ String sheetName=sheetModel.getSheetName(); String sheetToClone=sheetModel.getSheetToClone(); cloneSheet(sheetName, sheetToClone); } } private void cloneSheet(String sheetName,String sheetToClone ){ int sheetToCloneIdx=getSheetIndex(sheetToClone); cloneSheet(sheetToCloneIdx, sheetName); } private int getSheetIndex(String sheetName) throws SheetNotFoundException{ for (int i = 0; i < workbook.getNumberOfSheets(); i++) { if(workbook.getSheetAt(i).getSheetName().equals(sheetName) ) { return i; } } throw new SheetNotFoundException("Sheet '" + sheetName +"' not found" ); } public void cloneSheet(int index, String newSheetName) { HSSFSheet newSheet = workbook.cloneSheet(index); for (int i = 0; i < workbook.getNumberOfSheets(); i++) { if(newSheet.equals(workbook.getSheetAt(i))) { workbook.setSheetName(i, newSheetName); break; } } }
しかし、最も興味深いのはApache Commons JEXLライブラリです。
JEXLは、shell-scriptまたはECMAScriptで見られるほとんどの構造をサポートするJSTL Expression Languageの拡張に基づいてExpression Languageを実装します
以下は、サイトから少しやり直した例です。
// Create or retrieve a JexlEngine JexlEngine jexl = new JexlEngine(); // Create an expression object String jexlExp = "user.name"; Expression e = jexl.createExpression( jexlExp ); // Create a context and add data JexlContext jc = new MapContext(); jc.set("user", new User("") ); // Now evaluate the expression, getting the result Object o = e.evaluate(jc); o.toString(); // ""
したがって、すべてのタグをJavaコードにリストして、実際のデータと一致するように設定する必要はありません。
オブジェクトにのみ対応を設定するだけで十分です。その後、「タグ」をその値に置き換えるタスクは「タグ」の検索に減り、Commons JEXLにフィードして、タグの付いたセルにライブラリの結果を書き込みます。 混oticとして判明したので、例で説明しようとします。
テンプレートに「$ {user.name}、$ {user.age}」のような「タグ」を追加します。 また、Javaコードでは、Userクラスのオブジェクトをマップに配置するだけで十分です。
その後、ドキュメントのすべてのセルをループ処理し、「$ {」および「}」で制限された行を見つけて、それらの値をCommons JEXLライブラリの結果に置き換えます
private void fillSheet() { User user=new User("",25); // Map<String,Object> mappings=new HashMap<String,Object>(); mappings.put("user",user); JexlEngine engine=new JexlEngine(); JexlContext context=new MapContext(mappings); for(Row row : sheet) { for(Cell cell : row) { if(cell.getCellType()==Cell.CELL_TYPE_STRING){ String exp=findExpression(cell); if(exp!=null){ Expression e=engine.createExpression(exp); Object o=e.evaluate(context); if(o!=null){ String result=o.toString(); cell.setCellValue(result); } } } } } }
findExpression()メソッドは、セルに含まれる文字列で「$ {」と「}」で囲まれた部分文字列を検索します
JETTプロジェクトに会ったときに、Apache Commons JEXLライブラリについて学びました。 プロジェクトに多数のライブラリを追加したくありませんでした(JETTはさらにいくつかのライブラリに依存しています)。また、JETTのすべての機能は必要ありません。 しかし、それがどのように内部にあるかを理解するために、面白く配置されました:) 少なくとも誰かがこの投稿を手伝ってくれたら嬉しいです。