Controllare le dimensioni di un Workbook

di il
7 risposte

Controllare le dimensioni di un Workbook

Ciao a tutti, volevo una mano su un quesito su cui mi sto battendo in un progetto. Durante la creazione di un file Excel vorrei controllare se ogni 100 righe di scrittura ho superato una certa dimensione del file. L’obiettivo è quello di, nel caso interrompere la creazione, senza alterare le performance e consumare spazio del disco su cui sta lavorando, se ad esempio i file generati sono già troppo grandi. Sto usando l’Interfaccia pubblica Workbook. Ovviamente il mio applicativo deve interrompere il processo nel caso il file è già troppo grande durante la sua creazione parziale, altrimenti ritornare il file generato. Qualcuno può aiutarmi? Grazie

7 Risposte

  • Re: Controllare le dimensioni di un Workbook

    erik992 ha scritto:


    Durante la creazione di un file Excel vorrei controllare se ogni 100 righe di scrittura ho superato una certa dimensione del file. L’obiettivo è quello di, nel caso interrompere la creazione, senza alterare le performance e consumare spazio del disco su cui sta lavorando, se ad esempio i file generati sono già troppo grandi. Sto usando l’Interfaccia pubblica Workbook. Ovviamente il mio applicativo deve interrompere il processo nel caso il file è già troppo grande durante la sua creazione parziale, altrimenti ritornare il file generato.
    Non l'hai precisato ma si presume che stai usando la ben nota Apache POI. La questione è che Apache POI tiene tutto il workbook in memoria e poi solo alla fine lo si scrive da qualche parte (es. file) con il suo write(OutputStream) (o write(File) se si usa HSSFWorkbook). Quindi NON è affatto facile sapere o avere una stima di quella che poi sarebbe la dimensione del file finale.

    Innanzitutto si può vedere se la POI stessa può fornire una indicazione/stima. Vedo ad esempio che la HSSFWorkbook (quindi non la interfaccia Workbook) ha un byte[] getBytes() pertanto si può avere una stima, al costo di occupare memoria per l'array.

    Un'altra possibilità che non occupa memoria (ma un po' di tempo, invece) è implementare un OutputStream "nullo" cioè che non scrive nulla da alcuna parte ma che conta (in modo furbo) i byte che vengono scritti, così da avere la dimensione precisa. Chiaramente non fare questo solo ogni 100 righe ma magari ogni 1000 o 10000.
  • Re: Controllare le dimensioni di un Workbook

    Si puo' fare anche in modo piu' ""becero"":
    si prendono un po' di workbook contenenti il tipo di informazioni previste, si controlla la dimensione del file, il numero di righe,
    dim_riga = dim_file/num_righe
    si fa una media (tanto i valori non saranno TOTALMENTE diversi).

    Risultato, dal numero di righe si ha un'idea spannometrica della dimensione del file.

    Mica serve avere l'informazione al byte (non serve MAI, anche perche' COMUNQUE su disco il file e' salvato in pagine da 4K),
    giusto?
  • Re: Controllare le dimensioni di un Workbook

    Io avevo provato a fare una cosa del genere dove fileCount è un contatore di righe e fileSize è la dimensione massima accettabile, passata come input.
    Sto estraendo una serie di documenti da mongo e li voglio scrivere su un excel.
    i ... indicano una logica dedicata per la creazione del file.

    Ogni 100 righe dell'excel volevo fare il check sulle dimensioni.
    Solo alla fine se il numero di documenti non è multiplo di 100 devo rifare il controllo.
    Mi si genera un errore di I/OException, sembrerebbe che il problema sia nel non poter riutilizzare il workbook di appoggio dopo la sua chiusura (tramite il write).

    try (SXSSFWorkbook workbook = new SXSSFWorkbook()) {
    ...
    for (Document transaction : documents) {
    ...
    if (fileSize != null && fileCount == 100) {
    ByteArrayOutputStream partialStreamCheck = new ByteArrayOutputStream();
    workbook.write(partialStreamCheck);
    XSSFWorkbook partialWorkbook = workbook.getXSSFWorkbook();
    partialWorkbook.write(partialStreamCheck);

    if (fileSize != null) {
    sizeMB = (double)partialStreamCheck.size() / (1024 * 1024);
    if (sizeMB > fileSize.doubleValue()) {
    throw new ProjectException(ExceptionCode.LARGE_SIZE_FILE, null, "File size [" + sizeMB + " MB] is higher than the fixed limit [" + fileSize + " MB]");
    }
    }
    fileCount = 0;
    }
    totalTransactionCount++;
    }
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    workbook.write(outputStream);

    // // IF TRANSACTIONS ARE NOT MULTIPLES OF 100, LARGE SIZE FILE HAS TO BE CHECKED AGAIN
    if (fileSize != null && totalTransactionCount % 100 != 0) {
    sizeMB = (double)outputStream.size() / (1024 * 1024);
    if (sizeMB > fileSize.doubleValue()) {
    throw new ProjectException(ExceptionCode.LARGE_SIZE_FILE, null, "File size [" + sizeMB + " MB] is higher than the fixed limit [" + fileSize + " MB]");
    }
    }
    return outputStream.toByteArray();
    } catch (IOException e) {
    log.info(e.toString());
    } catch (ProjectException e) {
    throw new ProjectException(ExceptionCode.LARGE_SIZE_FILE, null, "File size [" + sizeMB + " MB] is higher than the fixed limit [" + fileSize + " MB]");
    }
    return null;
    }

    @andbin cosa intendi nell'utilizzare un Outputstream nullo?
    Grazie
  • Re: Controllare le dimensioni di un Workbook

    erik992 ha scritto:


    try (SXSSFWorkbook workbook = new SXSSFWorkbook()) {
    ...
    for (Document transaction : documents) {
    ...
    				if (fileSize != null && fileCount == 100) {
    					ByteArrayOutputStream partialStreamCheck = new ByteArrayOutputStream();
    					workbook.write(partialStreamCheck);
    					XSSFWorkbook partialWorkbook = workbook.getXSSFWorkbook();
    					partialWorkbook.write(partialStreamCheck);
    					
    					if (fileSize != null) {
    						sizeMB = (double)partialStreamCheck.size() / (1024 * 1024);
    						if (sizeMB > fileSize.doubleValue()) {
    							throw new ProjectException(ExceptionCode.LARGE_SIZE_FILE, null, "File size [" + sizeMB + " MB] is higher than the fixed limit [" + fileSize + " MB]");
    						}
    					}
    					fileCount = 0;
    				}
    				totalTransactionCount++;
    			}
    			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    			workbook.write(outputStream);
    
    			// // IF TRANSACTIONS ARE NOT MULTIPLES OF 100, LARGE SIZE FILE HAS TO BE CHECKED AGAIN
    			if (fileSize != null && totalTransactionCount % 100 != 0) {
    				sizeMB = (double)outputStream.size() / (1024 * 1024);
    				if (sizeMB > fileSize.doubleValue()) {
    					throw new ProjectException(ExceptionCode.LARGE_SIZE_FILE, null, "File size [" + sizeMB + " MB] is higher than the fixed limit [" + fileSize + " MB]");
    				}
    			}
    return outputStream.toByteArray();
    } catch (IOException e) {
    			log.info(e.toString());
    		} catch (ProjectException e) {
    			throw new ProjectException(ExceptionCode.LARGE_SIZE_FILE, null, "File size [" + sizeMB + " MB] is higher than the fixed limit [" + fileSize + " MB]");
    		}
    return null;
    }
    Mi pare una cosa molto "rocambolesca". E tra l'altro, stai usando SXSSFWorkbook che è la versione in "streaming" per cui il documento NON viene tenuto tutto in memoria ma c'è solo una "finestra" di righe disponibile.

    erik992 ha scritto:


    @andbin cosa intendi nell'utilizzare un Outputstream nullo?
    Estendere OutputStream per fare una implementazione dei suoi 3 metodi write che non scrivono da alcuna parte ma totalizzano solo il numero di byte scritti.
  • Re: Controllare le dimensioni di un Workbook

    Non l'ho ben chiaro.. potresti farmi un esempio? Ti ringrazio
  • Re: Controllare le dimensioni di un Workbook

    Ho provato ad usare HSSFWorkbook ma non va bene per gli xlsx. Il mio applicativo necessita di gestire anche quel formato.
  • Re: Controllare le dimensioni di un Workbook

    erik992 ha scritto:


    Ho provato ad usare HSSFWorkbook ma non va bene per gli xlsx. Il mio applicativo necessita di gestire anche quel formato.
    Considera:
    HSSF ---> .xls (il formato "binario" proprietario Microsoft)
    XSSF ---> .xlsx (il formato XML zippato; il Office Open XML)
Devi accedere o registrarti per scrivere nel forum
7 risposte