Halloweenská akce! Na stránce s dobitím bodů zadej dole kód STRASIDELNYCH20 a získej porci +20% bodů zdarma!
Akce končí 31.10. o půlnoci.

Diskuze: Java POI - Aktualizace dat

Java Java Java POI - Aktualizace dat American English version English version

Aktivity (1)
Avatar
Elix Novel
Člen
Avatar
Elix Novel:1. srpna 13:23

Zdravím, pracuji na programu, který bude umět aktualizovat data v souboru xlsx. Program by měl načíst soubor .txt, ve kterém budou nové buňky - oddělené středníkem a poté je zapsat do již existujícího souboru .xlsx.
Už nad tím bádám strašně dlouho a nemůžu na to přijít.

Zkusil jsem: Program by měl načíst workbook ze starého .xlsx souboru. Poté zjistit počet buněk v souboru a zavolat funkci pro aktualizaci dat. Funkce načte textový soubor a vše co je v textovém souboru na stejném místě jako ve starém xlsx souboru tak přepíše novými daty. Aby program poznal jak oddělovat buňky používám oddělovač středník. Všechny data ukládá do dočasného souboru, který poté přepíše na aktualizovaný soubor ,,vystup.xlsx"

public class TestUpdate {

    public static void main(String[] args) throws IOException, InvalidFormatException {
        XSSFWorkbook workbook = new XSSFWorkbook(new File("excel.xlsx"));

        for (int s = 0; s < workbook.getNumberOfSheets(); s++) {
            XSSFSheet sheet = (XSSFSheet) workbook.getSheetAt(s);
            update(sheet);
        }
    }

    public static void update(XSSFSheet sheet) throws FileNotFoundException, IOException {
        String unl = "textovySoubor.txt";
        File file = new File(unl);
        FileReader fileReader = new FileReader(file);
        BufferedReader br = new BufferedReader(fileReader);
        File temp = new File("temp.txt");
        String line = null;
        OutputStreamWriter osw = null;
        OutputStream os = null;
        BufferedWriter bw = null;
        os = (OutputStream) new FileOutputStream(temp);
        osw = new OutputStreamWriter(os);
        bw = new BufferedWriter(osw);

        while ((line = br.readLine()) != null) {
            String[] data = line.split(";");
            System.out.println();

        }
        for (int i = 0; i < sheet.getPhysicalNumberOfRows(); i++) {
            Row row = (Row) sheet.getRow(i);
            if (sheet.getPhysicalNumberOfRows() > 0) {
                bw.write(row.toString());
                bw.write(',');
                for (int j = 0; j < sheet.getPhysicalNumberOfRows(); j++) {
                    if (row.toString().contains(",")) {
                        bw.write(line);
                        bw.write(row.toString());
                        bw.write(line);

                    } else {
                        bw.write(row.toString());
                    }

                    bw.write(line);
                }
            }
            bw.newLine();

        }
        bw.flush();
        bw.close();
        File rename = new File("vystup.xlsx");
        temp.renameTo(rename);
    }
}

Chci docílit: Zkoušel jsem použít staré knihovny JExcel, ale tam není podpora nového formátu .xlsx (Excel 2007 a novější). Za každou pomoc budu strašně rád.

 
Odpovědět 1. srpna 13:23
Avatar
Odpovídá na Elix Novel
Matúš Olejník:1. srpna 13:53

Ahoj minimálne v tomto kúsku kódu kde načítavaš dáta z txt súboru, do poľa data, ktoré nikde nepoužiješ

while ((line = br.readLine()) != null) {
    String[] data = line.split(";");
    System.out.println();
}

namiesto toho chceš vkladať dáta z premennej line do ktorej síce v tom cykle vyššie postupne načítavaš riadky, ale robíš to mimo for cyklu v ktorom chceš zapisovať do nového súboru.

Rovnako veľmi nechápem ako presne to chceš mergnúť mohol by si poslať obrázok pôvodnej tabuľky, txt súbor ktorým ju chceš aktualizovať a obrázok excelu ako by to malo na konci vyzerať (sťačí pár riadkov, ktoré zvládneš aj ručne) ;)

Editováno 1. srpna 13:53
Nahoru Odpovědět 1. srpna 13:53
/* I am not sure why this works but it fixes the problem */
Avatar
Elix Novel
Člen
Avatar
Elix Novel:1. srpna 14:22

Ahoj, tady ti posílám obrázky jak by to mělo fungovat.
Původní .xlsx soubor:
https://imgur.com/a/Cl4TcmO
Textový soubor pro záměnu dat:
https://imgur.com/a/qslxTyB
A výsledný sobubor .xlsx:
https://imgur.com/a/i73vAcR

Editováno 1. srpna 14:22
 
Nahoru Odpovědět 1. srpna 14:22
Avatar
Odpovídá na Elix Novel
Matúš Olejník:1. srpna 15:08

Na nečisto lebo musím ísť od PC ale zatial skús postupne zavolať metódy ako sú v poradí

public void createWorkBook(File excelFile) {
    try {
        FileInputStream fis = new FileInputStream(excelFile);
        workbook = WorkbookFactory.create(fis);
    } catch (IOException | InvalidFormatException | EncryptedDocumentException ex) { //rozbit po jednom
        ex.printStackTrace();
    }
}

public void loadSheet(int sheetNumber) {
    try {
        sheet = workbook.getSheetAt(sheetNumber);
    }
    catch (EncryptedDocumentException ex) {
        ex.printStackTrace();
    }
}

public void update(){
    try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
        String line = br.readLine();
        int rowIndex = 0;
        while (line != null) {
            String[] cells = line.split(";");
            for(int col = 0; col < cells.length; col++){
                sheet.getRow(rowIndex).createCell(col).setCellValue(cells[col]);
            }
            rowIndex++;
            line = br.readLine();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

plus nejaký save, záloha atď

Nahoru Odpovědět 1. srpna 15:08
/* I am not sure why this works but it fixes the problem */
Avatar
Elix Novel
Člen
Avatar
Elix Novel:1. srpna 19:06

Ahoj, zkusil jsem si ten kód přepsat a udělat jak jsi říkal. Sice se mi program spustí a napíše ,,BUILD SUCCESSFUL", ale bohužel se mi nevytvoří výsledný soubor. Už jsem z toho opravdu bezradný, mohl by jsi mi s tím, prosím, pomoci ještě víc?

 
Nahoru Odpovědět 1. srpna 19:06
Avatar
Odpovídá na Elix Novel
Matúš Olejník:1. srpna 20:18

Takto mi to funguje, aj keď, keď to píšeš do txt súboru tak by si to nemohol rovno upravovať v tom exceli? :D

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

public class TestUpdate {

    private Sheet sheet;
    private Workbook workbook;
    private File excelFile;

    public void backupFile(){
        File file = excelFile;
            File backup = new File("backup"
                    + file.getName().substring(file.getName().lastIndexOf(".")));
            try {
                Files.copy(excelFile.toPath(), backup.toPath(), StandardCopyOption.REPLACE_EXISTING);
            }
            catch (IOException ex) {
                ex.printStackTrace();
            }
    }

    public void createWorkBook(File excelFile) {
        try {
            this.excelFile = excelFile;
            FileInputStream fis = new FileInputStream(excelFile);
            workbook = WorkbookFactory.create(fis);
        } catch (IOException | InvalidFormatException | EncryptedDocumentException ex) { //rozbit po jednom
            ex.printStackTrace();
        }
    }

    public void loadSheet(int sheetNumber) {
        try {
            sheet = workbook.getSheetAt(sheetNumber);
        }
        catch (EncryptedDocumentException ex) {
            ex.printStackTrace();
        }
    }

    public void update(File txtFile){
        try(BufferedReader br = new BufferedReader(new FileReader(txtFile))) {
            String line = br.readLine();
            int rowIndex = 0;
            while (line != null) {
                String[] cells = line.split(";");
                for(int col = 0; col < cells.length; col++){
                    sheet.getRow(rowIndex).createCell(col).setCellValue(cells[col]);
                }
                rowIndex++;
                line = br.readLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void saveFile() {
        try {
            FileOutputStream fileOut = new FileOutputStream(excelFile);
            workbook.write(fileOut);
            fileOut.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

import java.io.File;

public class MainClass {

    public static void main(String[] args){
        TestUpdate t = new TestUpdate();
        t.createWorkBook(new File("excelFile.xlsx"));
        t.backupFile();
        t.loadSheet(0);
        t.update(new File("txtFile.txt"));
        t.saveFile();
    }
}
Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
Nahoru Odpovědět 1. srpna 20:18
/* I am not sure why this works but it fixes the problem */
Avatar
Elix Novel
Člen
Avatar
Elix Novel:1. srpna 21:16

No asi by to bylo jednodušší, ale řeším problém, že spousty souborů mám v .txt a potřebuji je převést do excelu bez toho, abych to musel vše složitě opisovat. A povedlo se mi je překonvertovat, ale když jsem zjistil, že mám víc souborů pro jednu tabulku tak jsem začal řešit tenhle problém a nemohl na něj přijít.
Každopádně mi to teď vyhazuje chybu ,,java.lang.Nu­llPointerExcep­tion", a když smažu cyklus ,,while (line != null)" tak to funguje bez problému, ale zase se mi nevytvoří ten soubor.. Tak já už nevím kde dělám chybu.. :(
Každopádně moc děkuji za pomoc!

 
Nahoru Odpovědět 1. srpna 21:16
Avatar
Odpovídá na Elix Novel
Matúš Olejník:1. srpna 21:40

Taktiež môžeš ten txt súbor uložiť ako CSV a v exceli prejsť do Údaje -> Z textu -> Vybrať ten CSV súbor -> Vyskočí nastavenie tam vyberieš ako oddelovač bodkočiarku a dokončíš nastavenie a máš to v tabuľke.

No a krajšiu chybu ako NullPointerEx­ception si ani dostať nemohol :D Malo by ti tam písať aj viacero textu k tomu a dokonca aj riadok kde bola, skopíruj to sem. Cestu k súboru si dal správnu? Prípade sem hoď svoj kód, ale tak ako som to poslal to funguje.

Editováno 1. srpna 21:42
Nahoru Odpovědět 1. srpna 21:40
/* I am not sure why this works but it fixes the problem */
Avatar
Elix Novel
Člen
Avatar
Elix Novel:1. srpna 21:52

No to mě popravdě ani nenapadlo, každopádně teď už bych to chtěl dotáhnout přes tu Javu.
Chybu mi to vypsalo takto:

Exception in thread "main" java.lang.NullPo­interException
at testupdate.Up­date.update(Up­date.java:64)
at testupdate.Tes­tUpdate.main(Tes­tUpdate.java:12)
/home/radek/.cache/net­beans/8.2/exe­cutor-snippets/run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)

Myslím, že cestu jsem nastavil dobře a kód ti ještě dám sem:

public static void main(String[] args) {
    Update t = new Update();
    t.createWorkBook(new File("excel.xlsx"));
    t.backupFile();
    t.loadSheet(0);
    t.update(new File("test.txt"));
    t.saveFile();

}
public class Update {

    private Sheet sheet;
    private Workbook workbook;
    private File excelFile;

    public void backupFile() {
        File file = excelFile;
        File backup = new File("backup"
                + file.getName().substring(file.getName().lastIndexOf(".")));
        try {
            Files.copy(excelFile.toPath(), backup.toPath(), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public void createWorkBook(File excelFile) {
        try {
            this.excelFile = excelFile;
            FileInputStream fis = new FileInputStream(excelFile);
            workbook = WorkbookFactory.create(fis);
        } catch (IOException | InvalidFormatException | EncryptedDocumentException ex) { //rozbit po jednom
            ex.printStackTrace();
        }
    }

    public void loadSheet(int sheetNumber) {
        try {
            sheet = workbook.getSheetAt(sheetNumber);
        } catch (EncryptedDocumentException ex) {
            ex.printStackTrace();
        }
    }

    public void update(File txtFile) {
        try (BufferedReader br = new BufferedReader(new FileReader(txtFile))) {
            String line = br.readLine();
            int rowIndex = 0;
            while (line != null) {
                String[] cells = line.split(";");
                for (int col = 0; col < cells.length; col++) {
                    sheet.getRow(rowIndex).createCell(col).setCellValue(cells[col]);
                }
                rowIndex++;
                line = br.readLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void saveFile() {
        try {
            FileOutputStream fileOut = new FileOutputStream(excelFile);
            workbook.write(fileOut);
            fileOut.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}
 
Nahoru Odpovědět 1. srpna 21:52
Avatar
Odpovídá na Elix Novel
Matúš Olejník:1. srpna 23:08

Skús upraviť ten while takto

while (line != null) {
    String[] cells = line.split(";");
    if(sheet.getRow(rowIndex) == null) {
        sheet.createRow(rowIndex);
    }
    for(int col = 0; col < cells.length; col++){
        sheet.getRow(rowIndex).createCell(col).setCellValue(cells[col]);
    }
    rowIndex++;
    line = br.readLine();
}
Nahoru Odpovědět 1. srpna 23:08
/* I am not sure why this works but it fixes the problem */
Avatar
Elix Novel
Člen
Avatar
Elix Novel:2. srpna 19:20

Skvěle! Už vše funguje jak má, strašně moc ti děkuji za ochotu a tvůj čas. :) Můžu mít ještě poslední dotaz před uzavřením tohoto vlákna?
Narazil jsem na problém. Potřeboval bych tam přidat podmínku, že pokud se liší záhlaví sloupců u těchto dvou soborů tak se aktualizace dat neprovede. Zkusil jsem tedy načíst první řádek souboru .xlsx a poté první řádek souboru .txt a pak dát podmínku, ale bohužel z nějakého důvodu mi to nedovoluje to porovnat.

public void update(File txtFile) {
    try (BufferedReader br = new BufferedReader(new FileReader(txtFile))) {
        String line = br.readLine();
        int rowIndex = 0;
        Sheet prvniRadek = workbook.getSheetAt(0);
        String text = br.readLine();
        if(prvniRadek == text) {
        while (line != null) {
            String[] cells = line.split(";");
            if (sheet.getRow(rowIndex) == null) {
                sheet.createRow(rowIndex);
            }
    for(int col = 0; col < cells.length; col++){
    sheet.getRow(rowIndex).createCell(col).setCellValue(cells[col]);
}
            rowIndex++;
            line = br.readLine();
        } }
    } catch (IOException e) {
        e.printStackTrace();
    }
}
Editováno 2. srpna 19:22
 
Nahoru Odpovědět 2. srpna 19:20
Avatar
Odpovídá na Elix Novel
Petr Štechmüller:2. srpna 19:25

Ahoj, nefunguje Ti to, protože to špatně porovnáváš. Přečti si tady rozdíl mezi == a equals.
A hlavně porovnáváš dvě neporovnatelné věci.

if(prvniRadek == text)

Na jedné straně máš instanci typu Sheet a na druhé straně instanci typu String. Je tedy potřeba nejdříve srovnat typy instancí a pak je porovnat pomocí equals.

Nahoru Odpovědět 2. srpna 19:25
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Odpovídá na Elix Novel
Matúš Olejník:2. srpna 20:55

Rád som pomohol :) Ohľadom tej druhej otázky, tak vysvetlenie ti napísal Petr. Tu som napísal nejakú funkciu ako by si mohol porovnať zadaný riadok s dátami, hádam, že je veľa vecí ktoré by to mohli pokaziť, ale s tým už sa môžeš hrať ty ;)

public boolean rowEqualsData(Row row, String[] data){
    if(row.getLastCellNum() != data.length){
        return false;
    }
    for(int i = 0; i < data.length; i++){
        Cell cell = row.getCell(i);
        if(cell.getCellTypeEnum().equals(CellType.NUMERIC)){
            if(!String.valueOf(cell.getNumericCellValue()).equals(data[i])){
                return false;
            }
        } else if (cell.getCellTypeEnum().equals(CellType.STRING)){
            if(!cell.getStringCellValue().equals(data[i])){
                return false;
            }
        } else {
            throw new UnsupportedOperationException(
                "Comparing cell with cell type "
                    + cell.getCellTypeEnum().toString()
                    + " is not implemented yet"
            );
        }
    }

    return true;
}
Nahoru Odpovědět  +1 2. srpna 20:55
/* I am not sure why this works but it fixes the problem */
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 13 zpráv z 13.