2015-06-10 11 views
5

Attualmente sto lavorando con l'API Apache POI e sto cercando di modificare un documento Word con esso (*.docx). Un documento è composto da paragrafi (negli oggetti XWPFParagraph) e un paragrafo contiene testo incorporato in "corre" (XWPFRun). Un paragrafo può avere molte esecuzioni (a seconda delle proprietà del testo, ma a volte è casuale). Nel mio documento posso avere tag specifici che ho bisogno di sostituire con i dati (tutti i miei tag segue questo schema <#TAG_NAME#>)Ottieni l'elenco di oggetti contenenti testo corrispondente a un modello

Così, per esempio, se io elaboro un paragrafo che contiene il testo Some text with a tag <#SOMETAG#>, ho potuto ottenere qualcosa di simile

XWPFParagraph paragraph = ... // Get a paragraph from the document 
System.out.println(paragraph.getText()); 
// Prints: Some text with a tag <#SOMETAG#> 

Ma se voglio modificare il testo di quel paragrafo ho bisogno di elaborare le esecuzioni e il numero di esecuzioni non è fisso. Quindi, se mi mostra il contenuto di piste con quel codice:

System.out.println("Number of runs: " + paragraph.getRuns().size()); 
for (XWPFRun run : paragraph.getRuns()) { 
    System.out.println(run.text()); 
} 

A volte può essere così:

// Output: 
// Number of runs: 1 
// Some text with a tag <#SOMETAG#> 

E altro momento come questo

// Output: 
// Number of runs: 4 
// Some text with a tag 
// <# 
// SOMETAG 
// #> 

Cosa devo fare è quello di ottenere la prima esecuzione contenente l'inizio del tag e gli indici delle seguenti esecuzioni contenenti il ​​resto del tag (se il tag è diviso in più esecuzioni). Sono riuscito a ottenere una prima versione dell'algoritmo, ma funziona solo se l'inizio del tag (<#) e la fine del tag (#>) non sono divisi. Here's what I've already done.

Quindi quello che vorrei ottenere è un algoritmo in grado di gestire questo problema e, se possibile farlo funzionare con un dato tag (non necessariamente <# e #>, così ho potuto sostituirlo con qualcosa di simile {{{ e questo }}}).

Scusate se il mio inglese non è perfetto, non esitate a chiedermi di chiarire qualsiasi punto vogliate.

+0

È possibile concatenare tutte le esecuzioni di un paragrafo, aggiornare il testo e quindi sostituire le esecuzioni con una singola contenente il nuovo testo? Può essere che tu possa farlo funzionare usando: http://stackoverflow.com/a/3638229/2611083 –

+0

Questo è ciò che la mia soluzione effettiva fa parzialmente (se il tag è diviso in più esecuzioni, concatena il testo delle seguenti esecuzioni nel prima eseguire e cancellarli). Non voglio concatenare tutte le esecuzioni nel primo perché perderò tutti i parametri di testo. Ad esempio, se il paragrafo è ** Dati: ** _ _ <#DATATAG#>, voglio continuare "Dati:" in grassetto e sostituire il <#DATATAG#> dai dati che ho bisogno e tenerlo in corsivo –

+0

Se tutto il tag ha la stessi parametri, potrebbe essere in diverse esecuzioni? –

risposta

2

Finalmente ho trovato la risposta me stesso, ho cambiato totalmente il mio modo di pensare il mio algoritmo originale (ho commentato che quindi potrebbe aiutare qualcuno che potrebbe essere nella stessa situazione in cui mi trovavo)

// Before using the function, I'm sure that: 
// paragraph.getText().contains(surroundedTag) == true 
private void editParagraphWithData(XWPFParagraph paragraph, String surroundedTag, String replacement) { 
    List<Integer> runsToRemove = new LinkedList<Integer>(); 
    StringBuilder tmpText = new StringBuilder(); 
    int runCursor = 0; 

    // Processing (in normal order) the all runs until I found my surroundedTag 
    while (!tmpText.toString().contains(surroundedTag)) { 
     tmpText.append(paragraph.getRuns().get(runCursor).text()); 
     runsToRemove.add(runCursor); 
     runCursor++; 
    } 

    tmpText = new StringBuilder(); 
    // Processing back (in reverse order) to only keep the runs I need to edit/remove 
    while (!tmpText.toString().contains(surroundedTag)) { 
     runCursor--; 
     tmpText.insert(0, paragraph.getRuns().get(runCursor).text()); 
    } 

    // Edit the first run of the tag 
    XWPFRun runToEdit = paragraph.getRuns().get(runCursor); 
    runToEdit.setText(tmpText.toString().replaceAll(surroundedTag, replacement), 0); 

    // Forget the runs I don't to remove 
    while (runCursor >= 0) { 
     runsToRemove.remove(0); 
     runCursor--; 
    } 

    // Remove the unused runs 
    Collections.reverse(runsToRemove); 
    for (Integer runToRemove : runsToRemove) { 
     paragraph.removeRun(runToRemove); 
    } 
} 

Così ora sto elaborando tutte le esecuzioni del paragrafo finché non ho trovato il mio tag circondato, quindi sto elaborando il paragrafo per ignorare le prime esecuzioni se non ho bisogno di modificarle.

0

A volte il testo nei file DOCX viene suddiviso in un numero arbitrario di esecuzioni.

Problemi correlati