2cf039ed8b4619afadd7093d4c9785f84c8c3d10
[nucalgen] / nucalgen / src / main / java / jp / satomichan / nucalgen / Nucalgen.java
1 package jp.satomichan.nucalgen;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.util.ArrayList;
7 import java.util.HashMap;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Map.Entry;
11 import java.util.regex.Matcher;
12
13 import org.apache.commons.cli.CommandLine;
14 import org.apache.commons.cli.CommandLineParser;
15 import org.apache.commons.cli.DefaultParser;
16 import org.apache.commons.cli.Option;
17 import org.apache.commons.cli.Options;
18 import org.apache.poi.ss.usermodel.Cell;
19 import org.apache.poi.ss.usermodel.Row;
20 import org.apache.poi.ss.usermodel.Sheet;
21 import org.apache.poi.ss.usermodel.Workbook;
22 import org.apache.poi.ss.usermodel.WorkbookFactory;
23 import org.apache.poi.ss.util.CellRangeAddress;
24 import org.apache.poi.ss.util.CellReference;
25
26 import jp.satomichan.nucalgen.addition.AcCell;
27 import jp.satomichan.nucalgen.addition.AcRow;
28 import jp.satomichan.nucalgen.addition.AdditionConfig;
29 import jp.satomichan.nucalgen.addition.AdditionUtil;
30
31 public class Nucalgen {
32         private static final int COL_INDEX_START = 4;
33
34         public static void main(String[] args) {
35                 //コマンドライン・オプション読み込み
36                 Options options = new Options();
37                 options.addOption(Option.builder("s").required().hasArg().longOpt("std-food-comp-table").build());
38                 options.addOption(Option.builder("c").required().hasArg().longOpt("columns").build());
39                 options.addOption(Option.builder("o").required().hasArg().longOpt("output").build());
40                 options.addOption(Option.builder("l").required().hasArg().longOpt("lines").build());
41                 options.addOption(Option.builder("add").hasArgs().longOpt("addition").build());
42                 options.addOption(Option.builder("bright").hasArg().longOpt("bright-colored-vegetables-list").build());
43                 options.addOption(Option.builder("protect").longOpt("set-protect").build());
44                 options.addOption(Option.builder("processed").longOpt("use-processed-table").build());
45
46                 Map<String, String> namedAreaMap = new HashMap<String, String>();
47
48                 try {
49
50                         CommandLineParser parser = new DefaultParser();
51                         CommandLine cmd = parser.parse(options, args);
52
53                         final String mextStdFoodCompTableFileName = cmd.getOptionValue("std-food-comp-table");
54                         final String columnsXmlFileName = cmd.getOptionValue("columns");
55                         final String outputXlsxFileName = cmd.getOptionValue("output");
56                         final int lines = Integer.parseInt(cmd.getOptionValue("lines"));
57
58                         //コンフィグ読み込み
59                         NutritionColumnHolder nch = new NutritionColumnHolder(columnsXmlFileName);
60
61                         //Book生成
62                         Workbook outputWorkbook = WorkbookFactory.create(new FileInputStream(mextStdFoodCompTableFileName));
63
64                         if(cmd.hasOption("use-processed-table") == false) {
65                                 //成分表 変換
66                                 MextStdFoodCompTable stdCompTable = new MextStdFoodCompTable(cmd.getOptionValue("bright-colored-vegetables-list"));
67                                 stdCompTable.processInto(outputWorkbook);
68                         }
69
70
71                         //「栄養価計算」シート生成
72                         Sheet calcSheet = outputWorkbook.createSheet("栄養価計算");
73                         outputWorkbook.setSheetOrder("栄養価計算", 0);
74                         if(cmd.hasOption("set-protect")) {
75                                 calcSheet.protectSheet("");
76                         }
77                         calcSheet.setColumnWidth(2, 10240);
78                         calcSheet.addMergedRegion(new CellRangeAddress(1, 2, 1, 1));
79
80                         CellStylePool csPool = new CellStylePool(outputWorkbook);
81
82                         //「タイトル」行
83                         Row titleRow = calcSheet.createRow(1);
84                         titleRow.createCell(1).setCellValue("食品番号");
85                         titleRow.createCell(2).setCellValue("食品名");
86                         titleRow.createCell(3).setCellValue("摂取量");
87                         int colIndex = COL_INDEX_START;
88                         for(NutritionColumn aColumn : nch.getNutritionColumnList()) {
89                                 titleRow.createCell(colIndex).setCellValue(aColumn.getDispName());
90                                 colIndex++;
91                         }
92
93                         //「単位」行
94                         Row unitRow = calcSheet.createRow(2);
95                         unitRow.createCell(2).setCellValue("単位");
96                         unitRow.createCell(3).setCellValue("g");
97                         colIndex = COL_INDEX_START;
98                         for(NutritionColumn aColumn : nch.getNutritionColumnList()) {
99                                 unitRow.createCell(colIndex).setCellValue(aColumn.getUnit());
100                                 colIndex++;
101                         }
102
103                         //「栄養計算」行
104                         List<String> usedTableList = new ArrayList<String>();
105                         int rowIndex = 3;
106                         for(int i = rowIndex; i < lines + 3; i++,rowIndex++) {
107                                 Row thisRow = calcSheet.createRow(rowIndex);
108
109                                 //「食品名」
110                                 thisRow.createCell(1).setCellStyle(csPool.getCellStyle("00000", false));
111                                 thisRow.createCell(2).setCellFormula("IFERROR(VLOOKUP(B" + (rowIndex + 1) + ",成分表!$B$13:$BL$2500,3,FALSE),\"\")");
112                                 thisRow.createCell(3).setCellStyle(csPool.getCellStyle("", false));
113
114                                 colIndex = COL_INDEX_START;
115                                 for(NutritionColumn aColumn : nch.getNutritionColumnList()) {
116                                         Cell thisCell = thisRow.createCell(colIndex);
117                                         thisCell.setCellStyle(csPool.getCellStyle(aColumn.getFormat()));
118
119                                         if(aColumn.getFormula().length() >= 1) {
120                                                 //「計算式」列
121                                                 String formula = "(" + aColumn.getFormula() + ")";
122                                                 for(String aAlias : nch.getNutritionAliasList()) {
123                                                         String cell = new CellReference(rowIndex, 4 + nch.indexOf(aAlias)).formatAsString();
124                                                         formula = formula.replaceAll("([^A-Za-z0-9_])" + aAlias + "([^A-Za-z0-9_])", "$1" + cell + "$2");
125                                                 }
126                                                 thisCell.setCellFormula(formula);
127
128
129                                         } else {
130                                                 String div100 = aColumn.isUseRawValue() ? "" :  "/ 100 * $D" + (rowIndex + 1);
131                                                 thisCell.setCellFormula("IFERROR(VLOOKUP($B" + (rowIndex + 1) + "," + aColumn.getTable() + "!$B$13:$BL$2500,MATCH(\"" + aColumn.getName() + "\"," + aColumn.getTable() + "!$B$12:$BL$12,0),FALSE) " + div100 + ",\"\")");
132                                         }
133
134                                         colIndex++;
135
136                                         usedTableList.add(aColumn.getTable());
137                                 }
138
139                         }
140
141
142                         //摂取量 範囲を記憶
143                         String intakeArea = new CellReference(3, 3, true, true).formatAsString() + ":" + new CellReference(rowIndex -1, 3, true, true).formatAsString();
144                         namedAreaMap.put("AREA_INTAKE", intakeArea);
145
146
147                         //「合計」行
148                         Row sumRow = calcSheet.createRow(rowIndex);
149                         sumRow.createCell(1).setCellValue("合計");
150                         calcSheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, 3));
151                         colIndex = COL_INDEX_START;
152                         for(NutritionColumn aColumn : nch.getNutritionColumnList()) {
153                                 Cell thisCell = sumRow.createCell(colIndex);
154                                 String sumTargetArea = new CellReference(3, colIndex, true, true).formatAsString() + ":" + new CellReference(rowIndex -1, colIndex, true, true).formatAsString();
155
156                                 //範囲を記憶(alias あれば設定)
157                                 if(aColumn.getAlias().length() > 0) {
158                                         namedAreaMap.put("AREA_" + aColumn.getAlias(), sumTargetArea);
159
160                                         if(aColumn.isUseSum()) {
161                                                 String sumArea = new CellReference(rowIndex, colIndex, true, true).formatAsString();
162                                                 namedAreaMap.put("SUM_" + aColumn.getAlias(), sumArea);
163                                         }
164                                 }
165
166                                 thisCell.setCellStyle(csPool.getCellStyle(aColumn.getFormat()));
167                                 if(aColumn.isUseSum()) {
168                                         thisCell.setCellFormula("SUM(" + sumTargetArea + ")");
169                                 }
170                                 colIndex++;
171                         }
172
173                         
174                         //「付加行」出力
175                         String[] additionOptionValues = cmd.getOptionValues("addition");
176                         if(additionOptionValues != null) {
177                                 for(String aAdditionFileName : additionOptionValues) {
178                                         rowIndex += 3;
179                                         rowIndex = generateAddition(aAdditionFileName, calcSheet, csPool, rowIndex, namedAreaMap);
180                                 }
181                         }
182
183
184                         //未使用表シート削除
185                         for(int si = outputWorkbook.getNumberOfSheets() - 1 ; si >= 1 ; si--) {
186                                 String sheetName = outputWorkbook.getSheetName(si);
187                                 boolean used = false;
188                                 for(String usedTable : usedTableList) {
189                                         if(usedTable.equals(sheetName)) {
190                                                 used = true;
191                                         }
192                                 }
193                                 if(!used) {
194                                         outputWorkbook.removeSheetAt(si);
195                                 }
196                         }
197
198                         //ブック出力
199                         FileOutputStream outputXlsxFile = new FileOutputStream(outputXlsxFileName);
200                         outputWorkbook.setActiveSheet(0);
201                         calcSheet.setForceFormulaRecalculation(true);
202                         outputWorkbook.setSelectedTab(0);
203                         outputWorkbook.write(outputXlsxFile);
204                         outputWorkbook.close();
205
206                 } catch (Exception e) {
207                         // TODO 自動生成された catch ブロック
208                         e.printStackTrace();
209                 }
210         }
211
212
213
214
215         //「付加行」生成
216         private static int generateAddition(String fileName, Sheet calcSheet, CellStylePool csPool, int rowIndex,
217                                                                                                                                                                 Map<String,String> _namedAreaMap) {
218
219                 AdditionConfig ac = AdditionUtil.additionFileReader(new File(fileName));
220                 for(AcRow acRow : ac.getRows()) { //行ごとのループ
221                         Row thisRow = calcSheet.createRow(rowIndex);
222                         int colIndex = 0;
223                         
224                         for(AcCell acCell : acRow.getCells()) { //セルごとのループ
225                                 Cell thisCell = thisRow.createCell(colIndex);
226                                 
227                                 //alias 「付加行」内の別名定義(制約:右方・下方のセルからしか参照できない)
228                                 if(acCell.getAlias() != null) {
229                                         _namedAreaMap.put(acCell.getAlias(), new CellReference(rowIndex, colIndex, true, true).formatAsString());
230                                 }
231                                 
232                                 //formula 計算式
233                                 if(acCell.getFormula() != null){
234                                         String formula = "<" + acCell.getFormula() + ">";
235                                         for(Entry<String, String> keyValue : _namedAreaMap.entrySet()) {
236                                                 String k = keyValue.getKey();
237                                                 String v = keyValue.getValue();
238                                                 v = Matcher.quoteReplacement(v);
239                                                 formula = formula.replaceAll("([^A-Za-z0-9_])" + k + "([^A-Za-z0-9_])", "$1" + v + "$2");
240                                                 formula = formula.replaceAll("^<", "");
241                                                 formula = formula.replaceAll(">$", "");
242                                         }
243                                         thisCell.setCellFormula(formula);
244                                 
245                                 //value そのままの値
246                                 } else if(acCell.getValue() != null) {
247                                         thisCell.setCellValue(acCell.getValue());
248                                 
249                                 //formula でも value でもない
250                                 } else {
251                                         //
252                                 }
253                         
254                                 
255                                 colIndex++;
256                         } //セルごとのループ
257                         
258                         rowIndex++;
259                 } //行ごとのループ
260                 
261
262
263                 return rowIndex;
264         }
265
266
267
268
269
270
271
272 }