how to write data to excel using scriptom in groovy?

4k views Asked by At

I am reading properties and their values from soapUI and write them to an excel.

I am able to write the unique properties name into an excel

def oExcel = new ActiveXObject('Excel.Application')
Thread.sleep(1000)
assert oExcel != null, "Excel object not initalized"

def openWb = oExcel.Workbooks.Open(excelPath) //excelPath complete path to the excel
def dtUsedRange = openWb.Sheets(dataSheetName).UsedRange //dataSheetName is the name of teh sheet which will ultimately hold the data

//add property names to xlMapSheet under col d or col# 4
for(int r = 1;r<=uniqPropName.size().toInteger();r++){ //uniqPropName is a list that holds all the unique property names in a test suite
    openWb.Sheets(xlMapSheet).Cells(r,4).Value = uniqPropName[r-1]
}

oExcel.DisplayAlerts = false
openWb.Save
oExcel.DisplayAlerts = true

openWb.Close(false,null,false)
oExcel.Quit()
Scriptom.releaseApartment()

However now I have to write all the properties to the same excel. I have already created a map of the excel column names and soapUI properties so now i just have to find the matching excel col name from the map and write the property value under that excel.

I am using a function to do this stuff. This function is called from within a for loop which loops through all the properties in a test case. To this function I pass

sheetName //sheet where data has to be written
sheet //path of the excel file
pName //property name
pValue //property value
xMap //excel col name/heading map
tName //test case name
tsNum //step number

The relevant code for this function is below.

def write2Excel(sheetName,sheet,pName,pValue,xMap,tName,tsNum){

    //find the xl Col Name from the map


    def xl = new ActiveXObject('Excel.Application')
    assert xl != null, "Excel object not initalized"

    //open excel
    def wb = xl.Workbooks.Open(sheet)

    def rng = wb.Sheets(sheetName).UsedRange

    //get row count
    int iColumn = rng.Columns.Count.toInteger()
    int iRow = rng.Rows.Count.toInteger()

    //find column number using the col name

    //find the row with matching testcase name and step#

    //write data to excel
    if(rFound){ //if a row matching test case name and step number is found
          rng.Cells(r,colId).Value = pValue
    }else{
          rng = rng.Resize(r+1,iColumn) //if the testcase and step# row doesn't exist then the current range has to be extended to add one more row of data.
          rng.Cells(r+1,colId).Value = pValue
    }

    //save and close
    xl.DisplayAlerts = false
    wb.Save
    xl.DisplayAlerts = true

    wb.Close(false,null,false)
    xl.Quit()
    Scriptom.releaseApartment()
}

The code is currently running. It has been running since yesterday evening(2pm EST) so even if the code works it is not optimal. I can't wait this long to write data.

The curious thing is that the size of the excel keeps increasing which would mean that data is being written to the excel but i have check the excel and it has no new data..nothing..zilch!!

Evidence of increasing size of the file.

20/02/2014  04:23 PM           466,432 my_excel_file.xls
20/02/2014  04:23 PM           466,944 my_excel_file.xls
20/02/2014  04:38 PM           470,016 my_excel_file.xls
20/02/2014  04:45 PM           471,552 my_excel_file.xls
20/02/2014  04:47 PM           472,064 my_excel_file.xls
20/02/2014  05:01 PM           474,112 my_excel_file.xls
20/02/2014  05:01 PM           474,112 my_excel_file.xls
21/02/2014  07:23 AM           607,232 my_excel_file.xls
21/02/2014  07:32 AM           608,768 my_excel_file.xls
21/02/2014  07:50 AM           611,328 my_excel_file.xls

My questions are:
1. Why is data not being written when i am calling the function from within the for loop but getting written when i call it linear-ly?
2. In the first piece of code the excel process goes away when its done writing but when the function is run, the excel process remains even though its memory utilization goes up and down.

I am going to kill the excel process and instead of looping I am going to try and write only one or two sets of data using the function and will update this question accordingly.

1

There are 1 answers

0
Abhishek Asthana On BEST ANSWER

The process of opening an excel, writing to a cell, , save the excel, closing the excel is a time consuming task and when you multiply this with 300 test cases and ~15 properties per test, it can take significantly long. That is what has happening in my case and hence the process was taking forever to complete.

I am not 100% on why the size of the excel was increasing and nothing was getting written but i would guess that data was being kept in the memory and would have been written once the last cell was written, workbook saved and excel closed. This never happened because I didn't let it complete and would kill it when i realized that it has been running for an exceptionally long time.

In order to make this work, i changed my approach to the following.

  1. generate a map of col name and prop name
  2. generate a map of prop name and prop value for each test case. As one test case can have multiple property test steps, i create a multi map like this...
    [Step#:[propname:propvalue,....propname:propvalue]]
  3. create another map with col name and col id.
  4. Create a new map with col id and prop value. I made this using the above created maps.
  5. write data to excel. Because i already have the col id, and the value that goes into it. i don't do any checks and just write data to excel.

these steps are repeated for all test cases in the test suite. Using this process, i was able to complete my task within a few minutes.

I know i am using quite a few maps but this is the approach i could come up with. If anyone has a better approach, I would really like to try that out too.