web-dev-qa-db-fra.com

Comment insérer une ligne entre deux lignes dans un Excel existant avec HSSF (Apache POI)

D'une manière ou d'une autre, je parviens à créer de nouvelles lignes entre deux lignes dans un fichier Excel existant. Le problème est que certaines mises en forme n'ont pas été incluses lors du déplacement des lignes. 

L'une d'elles est que les rangées masquées ne sont pas relativement longues pendant le quart de travail. Ce que je veux dire, c’est (ex.), Les lignes de 20 à 30 sont masquées, mais lorsqu’elles créent de nouvelles lignes, la mise en forme existe toujours. Les lignes cachées doivent également se déplacer lors de l’insertion/création de nouvelles lignes, elles doivent être comprises entre 21 et 31. 

Une autre chose est que l'autre objet de la feuille ne se trouve pas dans la cellule. Comme la zone de texte ne sont pas déplacés après la création de la nouvelle ligne. Son comme la position de ces objets sont fixes. Mais je veux qu’il se déplace, comme si j’inscrivais une nouvelle ligne ou la collais dans Excel. S'il y a une fonction d'insertion d'une nouvelle ligne, s'il vous plaît faites le moi savoir.

C'est ce que j'ai en ce moment, juste un extrait de mon code.

HSSFWorkbook wb = new HSSFWorkbook(template); //template is the source of file
HSSFSheet sheet = wb.getSheet("SAMPLE");
HSSFRow newRow;
HSSFCell cellData;

int createNewRowAt = 9; //Add the new row between row 9 and 10

sheet.shiftRows(createNewRowAt, sheet.getLastRowNum(), 1, true, false);
newRow = sheet.createRow(createNewRowAt);
newRow = sheet.getRow(createNewRowAt);

Si copier et coller des lignes est possible, cela serait d'une grande aide. Mais je le demande déjà ici et je ne trouve pas de solution. J'ai donc décidé de créer une ligne en tant que solution provisoire. J'en ai fini avec ça, mais j'ai un problème comme ça. 

Toute aide sera très appréciée. Merci!

47
ace

Fonction d'assistance pour copier des lignes sans vergogne adaptées de ici

import org.Apache.poi.hssf.usermodel.*;
import org.Apache.poi.ss.usermodel.Cell;
import org.Apache.poi.ss.util.CellRangeAddress;

import Java.io.FileInputStream;
import Java.io.FileOutputStream;

public class RowCopy {

    public static void main(String[] args) throws Exception{
        HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream("c:/input.xls"));
        HSSFSheet sheet = workbook.getSheet("Sheet1");
        copyRow(workbook, sheet, 0, 1);
        FileOutputStream out = new FileOutputStream("c:/output.xls");
        workbook.write(out);
        out.close();
    }

    private static void copyRow(HSSFWorkbook workbook, HSSFSheet worksheet, int sourceRowNum, int destinationRowNum) {
        // Get the source / new row
        HSSFRow newRow = worksheet.getRow(destinationRowNum);
        HSSFRow sourceRow = worksheet.getRow(sourceRowNum);

        // If the row exist in destination, Push down all rows by 1 else create a new row
        if (newRow != null) {
            worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1);
        } else {
            newRow = worksheet.createRow(destinationRowNum);
        }

        // Loop through source columns to add to new row
        for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
            // Grab a copy of the old/new cell
            HSSFCell oldCell = sourceRow.getCell(i);
            HSSFCell newCell = newRow.createCell(i);

            // If the old cell is null jump to next cell
            if (oldCell == null) {
                newCell = null;
                continue;
            }

            // Copy style from old cell and apply to new cell
            HSSFCellStyle newCellStyle = workbook.createCellStyle();
            newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
            ;
            newCell.setCellStyle(newCellStyle);

            // If there is a cell comment, copy
            if (oldCell.getCellComment() != null) {
                newCell.setCellComment(oldCell.getCellComment());
            }

            // If there is a cell hyperlink, copy
            if (oldCell.getHyperlink() != null) {
                newCell.setHyperlink(oldCell.getHyperlink());
            }

            // Set the cell data type
            newCell.setCellType(oldCell.getCellType());

            // Set the cell data value
            switch (oldCell.getCellType()) {
                case Cell.CELL_TYPE_BLANK:
                    newCell.setCellValue(oldCell.getStringCellValue());
                    break;
                case Cell.CELL_TYPE_BOOLEAN:
                    newCell.setCellValue(oldCell.getBooleanCellValue());
                    break;
                case Cell.CELL_TYPE_ERROR:
                    newCell.setCellErrorValue(oldCell.getErrorCellValue());
                    break;
                case Cell.CELL_TYPE_FORMULA:
                    newCell.setCellFormula(oldCell.getCellFormula());
                    break;
                case Cell.CELL_TYPE_NUMERIC:
                    newCell.setCellValue(oldCell.getNumericCellValue());
                    break;
                case Cell.CELL_TYPE_STRING:
                    newCell.setCellValue(oldCell.getRichStringCellValue());
                    break;
            }
        }

        // If there are are any merged regions in the source row, copy to new row
        for (int i = 0; i < worksheet.getNumMergedRegions(); i++) {
            CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i);
            if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
                CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
                        (newRow.getRowNum() +
                                (cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow()
                                        )),
                        cellRangeAddress.getFirstColumn(),
                        cellRangeAddress.getLastColumn());
                worksheet.addMergedRegion(newCellRangeAddress);
            }
        }
    }
}
64
qwerty

Référencement Réponse de Qwerty , vous pouvez éviter de gonfler la taille de XL en réutilisant cellStyle. Et lorsque le type est CELL_TYPE_BLANK, getStringCellValue renvoie "" au lieu de null.

private static void copyRow(Sheet worksheet, int sourceRowNum, int destinationRowNum) {
  // Get the source / new row
  Row newRow = worksheet.getRow(destinationRowNum);
  Row sourceRow = worksheet.getRow(sourceRowNum);

  // If the row exist in destination, Push down all rows by 1 else create a new row
  if (newRow != null) {
    worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1);
  } else {
    newRow = worksheet.createRow(destinationRowNum);
  }

  // Loop through source columns to add to new row
  for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
    // Grab a copy of the old/new cell
    Cell oldCell = sourceRow.getCell(i);
    Cell newCell = newRow.createCell(i);

    // If the old cell is null jump to next cell
    if (oldCell == null) {
      newCell = null;
      continue;
    }

    // Use old cell style
    newCell.setCellStyle(oldCell.getCellStyle());

    // If there is a cell comment, copy
    if (newCell.getCellComment() != null) {
      newCell.setCellComment(oldCell.getCellComment());
    }

    // If there is a cell hyperlink, copy
    if (oldCell.getHyperlink() != null) {
      newCell.setHyperlink(oldCell.getHyperlink());
    }

    // Set the cell data type
    newCell.setCellType(oldCell.getCellType());

    // Set the cell data value
    switch (oldCell.getCellType()) {
    case Cell.CELL_TYPE_BLANK:
      break;
    case Cell.CELL_TYPE_BOOLEAN:
      newCell.setCellValue(oldCell.getBooleanCellValue());
      break;
    case Cell.CELL_TYPE_ERROR:
      newCell.setCellErrorValue(oldCell.getErrorCellValue());
      break;
    case Cell.CELL_TYPE_FORMULA:
      newCell.setCellFormula(oldCell.getCellFormula());
      break;
    case Cell.CELL_TYPE_NUMERIC:
      newCell.setCellValue(oldCell.getNumericCellValue());
      break;
    case Cell.CELL_TYPE_STRING:
      newCell.setCellValue(oldCell.getRichStringCellValue());
      break;
    }
  }
}
9
tcouery

Pour les personnes qui souhaitent insérer une ligne entre deux lignes dans un Excel existant avec XSSF (Apache POI), une méthode "copyRows" est déjà implémentée dans la feuille XSSFS.

import org.Apache.poi.ss.usermodel.CellCopyPolicy;
import org.Apache.poi.xssf.usermodel.XSSFSheet;
import org.Apache.poi.xssf.usermodel.XSSFWorkbook;
import Java.io.FileInputStream;
import Java.io.FileOutputStream;

public class App2 throws Exception{
    public static void main(String[] args){
        XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("input.xlsx"));
        XSSFSheet sheet = workbook.getSheet("Sheet1");
        sheet.copyRows(0, 2, 3, new CellCopyPolicy());
        FileOutputStream out = new FileOutputStream("output.xlsx");
        workbook.write(out);
        out.close();
    }
}
6
krishna

Référencement Réponse de Qwerty , si destRoy n'est pas null, sheet.shiftRows () changera la référence de destRow à la ligne suivante; Nous devrions donc toujours créer une nouvelle ligne:

if (destRow != null) {
  sheet.shiftRows(destination, sheet.getLastRowNum(), 1);
}
destRow = sheet.createRow(destination);
2
wanyz

J'ai fusionné certaines des autres réponses et commentaires dans l'implémentation suivante, testée avec Apache POI v3.9.

Je n'ai qu'un paramètre rownum parce que je décale la ligne cible et le copie dans la nouvelle ligne vide. Les formules sont gérées comme prévu, elles ne sont pas copiées telles quelles, à une exception près: les références aux cellules qui sont above la ligne copiée ne sont pas mises à jour; la solution de contournement consiste à remplacer ces références explicites (le cas échéant) par des références calculées à l'aide de INDIRECT() comme suggéré par this post .

protected void copyRow(Sheet worksheet, int rowNum) {
    Row sourceRow = worksheet.getRow(rowNum);

    //Save the text of any formula before they are altered by row shifting
    String[] formulasArray = new String[sourceRow.getLastCellNum()];
    for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
        if (sourceRow.getCell(i) != null && sourceRow.getCell(i).getCellType() == Cell.CELL_TYPE_FORMULA) 
            formulasArray[i] = sourceRow.getCell(i).getCellFormula();
    }

    worksheet.shiftRows(rowNum, worksheet.getLastRowNum(), 1);
    Row newRow = sourceRow;  //Now sourceRow is the empty line, so let's rename it
    sourceRow = worksheet.getRow(rowNum + 1);  //Now the source row is at rowNum+1

    // Loop through source columns to add to new row
    for (int i = 0; i < sourceRow.getLastCellNum(); i++) {
        // Grab a copy of the old/new cell
        Cell oldCell = sourceRow.getCell(i);
        Cell newCell;

        // If the old cell is null jump to next cell
        if (oldCell == null) {
            continue;
        } else {
            newCell = newRow.createCell(i);
        }

        // Copy style from old cell and apply to new cell
        CellStyle newCellStyle = worksheet.getWorkbook().createCellStyle();
        newCellStyle.cloneStyleFrom(oldCell.getCellStyle());
        newCell.setCellStyle(newCellStyle);

        // If there is a cell comment, copy
        if (oldCell.getCellComment() != null) {
            newCell.setCellComment(oldCell.getCellComment());
        }

        // If there is a cell hyperlink, copy
        if (oldCell.getHyperlink() != null) {
            newCell.setHyperlink(oldCell.getHyperlink());
        }

        // Set the cell data type
        newCell.setCellType(oldCell.getCellType());

        // Set the cell data value
        switch (oldCell.getCellType()) {
            case Cell.CELL_TYPE_BLANK:
                break;
            case Cell.CELL_TYPE_BOOLEAN:
                newCell.setCellValue(oldCell.getBooleanCellValue());
                break;
            case Cell.CELL_TYPE_ERROR:
                newCell.setCellErrorValue(oldCell.getErrorCellValue());
                break;
            case Cell.CELL_TYPE_FORMULA:
                newCell.setCellFormula(formulasArray[i]);
                break;
            case Cell.CELL_TYPE_NUMERIC:
                newCell.setCellValue(oldCell.getNumericCellValue());
                break;
            case Cell.CELL_TYPE_STRING:
                newCell.setCellValue(oldCell.getRichStringCellValue());
                break;
            default:   
                break; 
        }
    }

    // If there are any merged regions in the source row, copy to new row
    for (int i = 0; i < worksheet.getNumMergedRegions(); i++) {
        CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i);
        if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) {
            CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(),
                    (newRow.getRowNum() +
                            (cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow()
                                    )),
                    cellRangeAddress.getFirstColumn(),
                    cellRangeAddress.getLastColumn());
            worksheet.addMergedRegion(newCellRangeAddress);
        }
    }
}

J'utilise cette implémentation dans le code de production.

1
Pino

En ce qui concerne les formules "mises à jour" dans la nouvelle ligne, étant donné que toutes les copies ont lieu après le décalage, l'ancienne formule (maintenant un index sur la nouvelle) a déjà vu sa formule décalée. la nouvelle ligne fait référence aux anciennes cellules de lignes. Une solution serait d’analyser les formules AVANT le changement, puis de les appliquer (un simple tableau de chaînes ferait le travail. Je suis sûr que vous pouvez le coder en quelques lignes).

Au début de la fonction:

ArrayList<String> fArray = new ArrayList<String>();
Row origRow = sheet.getRow(sourceRow);
for (int i = 0; i < origRow.getLastCellNum(); i++) {
    if (origRow.getCell(i) != null && origRow.getCell(i).getCellType() == Cell.CELL_TYPE_FORMULA) 
        fArray.add(origRow.getCell(i).getCellFormula());
    else fArray.add(null);
}

Ensuite, lors de l'application de la formule à une cellule:

newCell.setCellFormula(fArray.get(i));
0
Anton Chertok

J'ai implémenté ceci dans Kotlin comme ceci:

fun Sheet.buildRow ( rowNum:Int ) : Row {
    val templateRow = this.getRow( rowNum )
    this.shiftRows( rowNum+1, sheet.lastRowNum, 1 )
    val newRow = this.createRow( rowNum+1 )
    templateRow.cellIterator().forEach {
        newRow.createCell( it.columnIndex ).cellStyle = it.cellStyle
    }
    return templateRow
}

Il ne copie pas les valeurs de cellule, mais seulement le format ..__ devrait également s'appliquer à Java.

0
Christoph

Je suis tombé sur le même problème récemment. J'ai dû insérer de nouvelles lignes dans un document avec des lignes cachées et j'ai rencontré les mêmes problèmes avec vous. Après quelques recherches et quelques courriels dans la liste de poi Apache, cela ressemble à un bogue dans shiftrows () lorsqu'un document a des lignes cachées.

0
SpyrosR