Hallo zusammen,
ich versuche Javacode zu schreiben der Einträge in einem String Array mit Zell-Einträgen eines Excel Workbooks vergleicht und fehlende Einträge hinzufügt.
Dafür nutze ich das Apache POI Framework (poi.apache.org).
Im Folgenden die Implementierung in einer Standalone Variante, die später in einen größeren Programmkontext verwendet werden soll:
Im Anhang findet sich eine entsprechende Exceldatei, die zum testen genutzt werden kann.
Ich habe zwei Fragen zu meiner Implementierung:
Ich bin ein ziemlicher Java-Anfänger. Ich gehe also davon aus, dass einige meiner Implementierungs-Entscheidungen unsinnig für das geschulte Auge wirken. In dem Fall bin ich gerne für Kritik offen. Zu Apache POI habe ich für Anfänger leider kaum brauchbare Tutorials finden können. Auch hier bin ich für Hinweise dankbar.
Beste Grüße
David
ich versuche Javacode zu schreiben der Einträge in einem String Array mit Zell-Einträgen eines Excel Workbooks vergleicht und fehlende Einträge hinzufügt.
Dafür nutze ich das Apache POI Framework (poi.apache.org).
Im Folgenden die Implementierung in einer Standalone Variante, die später in einen größeren Programmkontext verwendet werden soll:
Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Set;
import java.util.TreeMap;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ReadAndWriteExcel {
public static void main(String[] args){
String[][] newProjects = {{"a","ProjektA","1"},{"b","ProjektB","2"},{"c","ProjektC","3"}};
updateProjectList(newProjects);
}
public static void updateProjectList(String[][] newProjects){
File file = new File("projekte.xlsx");
boolean oldProject = false; //is set true, if a project is already listed in the Excel sheet
try{
//Get the workbook instance for XLSX file
FileInputStream fis = new FileInputStream(file);
XSSFWorkbook workbook = new XSSFWorkbook(fis);
XSSFSheet spreadsheet = workbook.getSheetAt(0);
TreeMap<String, Object[]> data = new TreeMap<String, Object[]>();
if(file.isFile() && file.exists()){
//Iterate through projects from newProjects String
for(int k = 0; k < newProjects.length; k++){
System.out.println("Stringeinträge:" + newProjects.length);
//Iterate through project rows in existing worksheet
for(int i = 0; i < spreadsheet.getLastRowNum() + 1;i++){
XSSFRow row = spreadsheet.getRow(i);
Cell cell = row.getCell(1);
System.out.println("k:"+k+" i:"+i);
//Check for Error Cells
switch(cell.getCellType()){
case Cell.CELL_TYPE_ERROR:
System.out.println("ERROR CELL at" + cell.getRowIndex());
break;
case Cell.CELL_TYPE_STRING :
if((cell.getStringCellValue()) != null){
//Check for new Projects
if(newProjects[k][1].equals(cell.getStringCellValue())){
oldProject = true;
}
}
break;
}
}
if(oldProject){
oldProject = false;
continue;
}
else{
data.put("1", new Object[]{newProjects[k][0], newProjects[k][1],newProjects[k][2]});
Set<String> keyset = data.keySet();
int rownum = spreadsheet.getLastRowNum() + 1;
for (String key : keyset){
XSSFRow row = spreadsheet.createRow(rownum++);
Object [] objArr = data.get(key);
int cellnum = 0;
for (Object obj : objArr){
Cell cell = row.createCell(cellnum++);
cell.setCellValue((String)obj);
}
}
}
}
}
fis.close();
try(FileOutputStream out = new FileOutputStream("projekte.xlsx")){
workbook.write(out);
System.out.println("projekte.xlsx updated successfully");
}catch(IOException e){
e.printStackTrace();
}
}catch(IOException e){
e.printStackTrace();;
}
}
}
Im Anhang findet sich eine entsprechende Exceldatei, die zum testen genutzt werden kann.
Ich habe zwei Fragen zu meiner Implementierung:
- Allgemein: Was ist generell von meiner Implementierung zu halten? Gibt es schönere Lösungen (die vor allem weniger Ressourcen brauchen)? Wenn ich das richtig beurtiele, so liegt die Komplexität bei a*b, wobei a = Einträge im String Array und b = Einträge in dem Excel Workbook. In der Praxis werde ich wohl auf 1000 x 1000 = 1.000.000 Durchläufe treffen.
- Speziell: Ich habe zwei unschöne Eigenschaften beim Testen entdeckt:
- Wenn das Programm feststellt, dass ein String aus dem Array im Excel Workbook fehlt, dann wird dieser String sofort in das Workbook eingetragen. Beim prüfen des nächsten Strings aus dem Array, wird dann der soeben angehängte String mit dem aktuellen verglichen. Das würde ich gerne vermeiden, da sonst bei steigender Arraygröße immer mehr Ressourcen gebraucht werden.
- Wenn man Einträge im Excel Workbook löscht (mit Excel oder über Code) bleiben leere Zellen zurück. Diese leeren Zellen werden auch beim Auslesen des Worksheet Inhalts übernommen, sodaß Lücken zwischen den Einträgen enstehen können. Stellt Apache POI eine einfach Funktion zur Verfügung, um leere Zeilen zu löschen?
- Wenn das Programm feststellt, dass ein String aus dem Array im Excel Workbook fehlt, dann wird dieser String sofort in das Workbook eingetragen. Beim prüfen des nächsten Strings aus dem Array, wird dann der soeben angehängte String mit dem aktuellen verglichen. Das würde ich gerne vermeiden, da sonst bei steigender Arraygröße immer mehr Ressourcen gebraucht werden.
Ich bin ein ziemlicher Java-Anfänger. Ich gehe also davon aus, dass einige meiner Implementierungs-Entscheidungen unsinnig für das geschulte Auge wirken. In dem Fall bin ich gerne für Kritik offen. Zu Apache POI habe ich für Anfänger leider kaum brauchbare Tutorials finden können. Auch hier bin ich für Hinweise dankbar.
Beste Grüße
David