Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find merged cell in Excel, split the cells and write those in new spreadsheet?

I have been given a Assignment that I need to Split the data of a Spreadsheet and Write it into the new Spreadsheet. The Conditions are, Given Spreadsheet may have multiple numbers of Merged Cells and I need to find those Merged cells and write those Data in a New SpreadSheet. ie, the data or cells between one merged cell till to another Merged cell must be written in another Spreadsheet.

My Code of Effort is given below,

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;


public class CopyTest {

public static void main(String[] args) throws IOException {
    CopyTest excel = new CopyTest();
    excel.process("D:\\B3.xls");
 }

public void process(String fileName) throws IOException {
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName));
    HSSFWorkbook workbook = new HSSFWorkbook(bis);
    HSSFWorkbook myWorkBook = new HSSFWorkbook();
    HSSFSheet sheet = null;
    HSSFRow row = null;
    HSSFCell cell = null;
    HSSFSheet mySheet = null;
    HSSFRow myRow = null;
    HSSFCell myCell = null;
    int sheets = workbook.getNumberOfSheets();
    int fCell = 0;
    int lCell = 0;
    int fRow = 0;
    int lRow = 0;

    for (int iSheet = 0; iSheet < sheets; iSheet++) {
        sheet = workbook.getSheetAt(iSheet);
        if (sheet != null) {
            mySheet = myWorkBook.createSheet(sheet.getSheetName());

            fRow = sheet.getFirstRowNum();
            System.out.println("First Row at"+fRow);
            lRow = sheet.getLastRowNum();
            for (int iRow = fRow; iRow <= lRow; iRow++) {
                row = sheet.getRow(iRow);
                myRow = mySheet.createRow(iRow);



                if (row != null) {
                    fCell = row.getFirstCellNum();
                    lCell = row.getLastCellNum();
                    for (int iCell = fCell; iCell < lCell; iCell++) {
                        //if (mySheet.getMergedRegionAt(index)!=null)
                       System.out.println("Finding next merged Cells");
                       cell = row.getCell(iCell);
                        myCell = myRow.createCell(iCell);
                        if (cell != null) {
                            myCell.setCellType(cell.getCellType());

                            switch (cell.getCellType()) {
                            case HSSFCell.CELL_TYPE_BLANK:
                                myCell.setCellValue("");
                                break;

                            case HSSFCell.CELL_TYPE_BOOLEAN:
                                myCell.setCellValue(cell.getBooleanCellValue());
                                break;

                            case HSSFCell.CELL_TYPE_ERROR:
                                myCell.setCellErrorValue(cell.getErrorCellValue());
                                break;

                            case HSSFCell.CELL_TYPE_FORMULA:
                                myCell.setCellFormula(cell.getCellFormula());
                                break;

                            case HSSFCell.CELL_TYPE_NUMERIC:
                                myCell.setCellValue(cell.getNumericCellValue());
                                break;

                            case HSSFCell.CELL_TYPE_STRING:
                                myCell.setCellValue(cell.getStringCellValue());
                                break;
                            default:
                                myCell.setCellFormula(cell.getCellFormula());
                               // System.out.println("Reading Cell value\t"+myCell);
                            }System.out.println("Reading Cell value\t"+myCell);
                        }
                    }
                }
            }
        }

    }  

    bis.close();
    BufferedOutputStream bos = new BufferedOutputStream(
            new FileOutputStream("D:\\Result Excel1.xls", true));
    myWorkBook.write(bos);
    bos.close();

 }}

With this Code, I have Achieved cloning the spreadsheet into another new Sheet. Here, I am failing to find the merged Cell, getMergedCellRegionAt() helps me and returns merged cell region like A:4 D:12 like that. how do I proceed with this. Kindly Help me, your small effort is appreciated. Thanks in advance.

like image 223
Java_User Avatar asked Aug 30 '13 09:08

Java_User


3 Answers

According to the Javadocs for HSSFSheet, getMergedCellRegionAt() was deprecated in 2008 because the Region it returns was also deprecated, in favor of CellRangeAddress. It suggests that you should use getMergedRegion(int) instead, which returns a CellRangeAddress.

The merged region data is not stored directly with the cells themselves, but with the Sheet object. So you do not need to loop through rows and cells looking for whether they are part of a merged region; you just need to loop through the list of merged regions on the sheet, then add the merged region to your new sheet with addMergedRegion(CellRangeAddress).

for (int i = 0; i < sheet.getNumMergedRegions(); i++)
{
    CellRangeAddress mergedRegion = sheet.getMergedRegion(i);
    // Just add it to the sheet on the new workbook.
    mySheet.addMergedRegion(mergedRegion);
}

These methods on HSSFSheet are in the Sheet interface, so they will work with any Excel workbook that Apache POI supports, .xls (HSSF) or .xlsx (XSSF).

like image 136
rgettman Avatar answered Sep 28 '22 03:09

rgettman


The merged cells have their value in the first cell.

The following method returns the value of the region provided the first cell's row and column in the merged region

String getMergedRegionStringValue(HSSFSheet sheet, int firstRow, int firstColumn){
   for(int i = 0; i < sheet.getNumMergedRegions(); i++) {
        CellRangeAddress region = sheet.getMergedRegion(i);

        int colIndex = region.getFirstColumn();
        int rowNum = region.getFirstRow();
        //check first cell of the region
        if(rowNum == firstRow && colIndex == firstColumn){  
            return sheet.getRow(rowNum).getCell(colIndex).getStringCellValue();
        }
    }
}
like image 44
Sorter Avatar answered Sep 28 '22 03:09

Sorter


rgettmans answer is completely correct.

Java 8

I just wanted to add a solution for Java 8 with streams:

Sheet oldSheet, newSheet;
IntStream.range(0, oldSheet.getNumMergedRegions())
           .mapToObj(oldSheet::getMergedRegion)
           .forEach(newSheet::addMergedRegion);
like image 41
winklerrr Avatar answered Sep 28 '22 04:09

winklerrr