Can't copy a Worksheet that contains a Chart using EPPLUS - excel

I'm trying to copy a worksheet that contains a chart, but when I try to do it, my code fires a "package relationship with specified id does not exist for the source part" exception, what are possible reasons for this? *If I remove the chart from the template, everything works fine.
Here's my code:
public void GenerateFromTemplate(DirectoryInfo outputPath, FileInfo templateFile,
string newFileName, List<Dictionary<string, string>> cellDataList)
{
try
{
using (ExcelPackage p = new ExcelPackage(templateFile, true))
{
bool first = true;
foreach (Dictionary<string, string> cellData in cellDataList) {
Logger.LogInfo("Adding new Sheet...");
ExcelWorksheet currentWorkSheet;
if (first)
{
currentWorkSheet = p.Workbook.Worksheets[1];
first = false;
}
else {
currentWorkSheet = p.Workbook.Worksheets.Copy("Ticker", "Ticker" + p.Workbook.Worksheets.Count);
}
foreach (KeyValuePair<string, string> cell in cellData)
{
Logger.LogInfo(cell.Key + "cell value set to" + cell.Value);
currentWorkSheet.Cells[cell.Key].Value = cell.Value;
}
}
Byte[] bin = p.GetAsByteArray();
string file = outputPath + newFileName;
Logger.LogInfo("Writing Excel File to " + file);
File.WriteAllBytes(file, bin);
Logger.LogInfo("Writing Done");
}
}
catch (Exception ex)
{
Logger.LogError(ex);
}
}
Regards!

Related

How to execute query on csv file

i have uploaded a csv file and also make a data-table from csv file.now i want to find distinct values from each columns of data-table.what will be the code for this.
i have tried by this code but there is error show that object is not ADODB.what is ADODB and how can i remove this error
public static DataTable GetDataTabletFromCSVFile(string csv_file_path)
{
DataTable csvData = new DataTable();
try
{
using (TextFieldParser csvReader = new TextFieldParser(csv_file_path))
{
csvReader.SetDelimiters(new string[] { "," });
csvReader.HasFieldsEnclosedInQuotes = true;
//read column names
string[] colFields = csvReader.ReadFields();
foreach (string column in colFields)
{
DataColumn datecolumn = new DataColumn(column);
datecolumn.AllowDBNull = true;
csvData.Columns.Add(datecolumn);
}
while (!csvReader.EndOfData)
{
string[] fieldData = csvReader.ReadFields();
//Making empty value as null
for (int i = 0; i < fieldData.Length; i++)
{
if (fieldData[i] == "")
{
fieldData[i] = null;
}
}
csvData.Rows.Add(fieldData);
}
foreach (DataColumn col in csvdata.Columns)
{
foreach (DataRow ro in csvdata.Rows)
{
textBox1.Text = "" + ro[col];
}
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}

Selenium excel read and write to find row number

In my program I want to find the row number in the excel sheet matching the string I have passed as argument . It works fine for first and second row but problem is with the next rows. My code to find row number is as below :
public int findrownum(String sName, String value, int cNum) throws Exception{
File excel = new File(filepath);
FileInputStream fis = new FileInputStream(excel);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet ws = wb.getSheet(sName);
boolean check = true;
int i=0;
while (check){
XSSFRow rowH = ws.getRow(i);
XSSFCell cell = rowH.getCell(cNum);
String cellvalue = cellToString(cell);
if (cellvalue.equals(value)){
check = false;
}
else {
i = i+1;
}
}
return i;
}
}
I want to read third row that is the string with name registration from the excel
Sl No test case name result timestamp
1 login Pass 03/03/2014 12:11:43 PM
2 Registration
Please let me know what changes needs to be done in the code .
Thanks
I used the similar logic as mentioned by #eric in JUNIT now i am able to find the row number .But now its giving error while i try to read the data using this row number . My code to read data is as below . Please let me know what changes needs to be done public String dataread(String sName, int rNum, String cName) throws Exception{
File excel = new File(filepath);
FileInputStream fis = new FileInputStream(excel);
XSSFWorkbook wb = new XSSFWorkbook(fis);
XSSFSheet ws = wb.getSheet(sName);
XSSFRow rowH = ws.getRow(rNum-1);
int totalRows = ws.getLastRowNum();
int i =0;
for(i=0;i<=totalRows;i++)
{
XSSFCell cell = rowH.getCell(i);
String value = cellToString(cell);
if (value.equals(cName)){
System.out.println(i);
break;
}
}
XSSFRow row = ws.getRow(rNum);
XSSFCell cell = row.getCell(i);
String value = cellToString(cell) return value;
}
In general From this Documentation you can use the getHeight() to get in which your cursor instead of writing up your own loop. Obviously this would reduce the execution time as well. Also the code which you have written could have caused the exception,as there is no more physical rows.
ws.getRow(i); can cause a fatal error if i>height of the last row
Hope the following code helps. The assumption is the data in the cell is string data. Also this is with apache poi api.
public static String getcellValue(int testRowNo, int colNo)
{
String projectPath = System.getProperty("user.dir");
String excelPath = projectPath + "/TestSet.xlsx";
File excel = new File(excelPath);
FileInputStream fis = null;
Workbook workBook = null;
String cellValue = null;
try
{
fis = new FileInputStream(excel);
workBook = WorkbookFactory.create(fis);
Sheet workSheet = workBook.getSheet(sheetName);
int totalRows = workSheet.getLastRowNum();
Row row = null;
cellValue = workSheet.getRow(testRowNo).getCell(colNo).getStringCellValue();
} catch (InvalidFormatException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}finally
{
try
{
fis.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
return cellValue;
}
public static int getrowNumber(String sheetName, String cellData)
{
String projectPath = System.getProperty("user.dir");
String excelPath = projectPath + "/TestSet.xlsx";
File excel = new File(excelPath);
FileInputStream fis = null;
Workbook workBook = null;
String cellValue = null;
try
{
fis = new FileInputStream(excel);
workBook = WorkbookFactory.create(fis);
Sheet workSheet = workBook.getSheet(sheetName);
int totalRows = workSheet.getLastRowNum();
Row row = null;
int testRowNo = 0;
for(int rowNo =1; rowNo<=totalRows; rowNo++)
{
row = workSheet.getRow(rowNo);
testRowNo = testRowNo +1;
if(row.getCell(0).getStringCellValue().equalsIgnoreCase(cellData))
{
break;
}
}
} catch (InvalidFormatException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
}finally
{
try
{
fis.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
return testRowNo;
}

XSSFSheet get all cell type values as string

Is there any possiblity to get all types(numeric,date,string etc) as String only.I couldn't find such methods.
sheet.getCell(rowIndex,colIndex) like this ?
InputStream ExcelFileToRead = new FileInputStream(file1);
XSSFWorkbook wb = new XSSFWorkbook(ExcelFileToRead);
XSSFWorkbook test = new XSSFWorkbook();
XSSFSheet sheet = wb.getSheetAt(0);
XSSFRow row;
XSSFCell cell;
Iterator rows = sheet.rowIterator();
String[] Excelarray=new String[26];
int count=0;
Map<String, String> data = new HashMap<String, String>();
while (rows.hasNext())
{
row=(XSSFRow) rows.next();
Iterator cells = row.cellIterator();
while (cells.hasNext())
{
cell=(XSSFCell) cells.next();
if (cell.getCellType() == XSSFCell.CELL_TYPE_STRING)
{
System.out.print(cell.getStringCellValue()+",");
}
else if(cell.getCellType() == XSSFCell.CELL_TYPE_NUMERIC)
{
System.out.print(cell.getNumericCellValue()+",");
}
else
{
}
}
System.out.println("----Closed");
}
Someone else already supplied a generic implementation that does what you are looking to do. POI doesn't have anything directly but it's easy enough to make a helper method/class.
Yes, It is possible to get all the values in the form of string.
Previously I had used DataFormatter to get the string value but while working with the large files I found it does not work so well.
Here is the required code: -
for (Row row : sheet) {
DataFormatter dataFormatter = new DataFormatter();
for (Cell cell : row) {
String cellValue = getStringCellValue(cell);
}
}
private static String getStringCellValue(Cell cell) {
try {
switch (cell.getCellType()) {
case FORMULA:
try {
return NumberToTextConverter.toText(cell.getNumericCellValue());
} catch (NumberFormatException e) {
return cell.getStringCellValue();
}
case NUMERIC:
return NumberToTextConverter.toText(cell.getNumericCellValue());
case STRING:
String cellValue = cell.getStringCellValue().trim();
String pattern = "\\^\\$?-?([1-9][0-9]{0,2}(,\\d{3})*(\\.\\d{0,2})?|[1-9]\\d*(\\.\\d{0,2})?|0(\\.\\d{0,2})?|(\\.\\d{1,2}))$|^-?\\$?([1-9]\\d{0,2}(,\\d{3})*(\\.\\d{0,2})?|[1-9]\\d*(\\.\\d{0,2})?|0(\\.\\d{0,2})?|(\\.\\d{1,2}))$|^\\(\\$?([1-9]\\d{0,2}(,\\d{3})*(\\.\\d{0,2})?|[1-9]\\d*(\\.\\d{0,2})?|0(\\.\\d{0,2})?|(\\.\\d{1,2}))\\)$";
if (((Pattern.compile(pattern)).matcher(cellValue)).find()) {
return cellValue.replaceAll("[^\\d.]", "");
}
return cellValue.trim();
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case ERROR:
return null;
default:
return cell.getStringCellValue();
}
} catch (Exception e) {
if (e.getLocalizedMessage() != null && ConfigReader.isDisplayWarnLog())
return "";
}
return "";
}
It works well. Thank You.

DataTable to excel conversion

I have a datagrid which populates a datatable, I want to export the DataTable to excel on click of a button. I am using MVVM for this application. So is it ok to implement the export feature in my view?
Secondly, as i am using xaml and desktop application, how do i capture the grid and its details.
Can any one suggest me some pointers? I am new to this.
Thanks,
Sagar
This is what i have done and it helped me:
private readonly ICommand m_ExportButtonClick;
private string ExcelFilePath = "";
public ICommand ExportButtonClick { get { return m_ExportButtonClick; } }
private void OnRunExport()
{
try
{
if (queryDatatable == null || queryDatatable.Columns.Count == 0)
throw new Exception("ExportToExcel: Null or empty input table!\n");
// load excel, and create a new workbook
Excell.Application excelApp = new Excell.Application();
excelApp.Workbooks.Add();
// single worksheet
Excell._Worksheet workSheet = excelApp.ActiveSheet;
// column headings
for (int i = 0; i < queryDatatable.Columns.Count; i++)
{
workSheet.Cells[1, (i + 1)] = queryDatatable.Columns[i].ColumnName;
}
// rows
for (int i = 0; i < queryDatatable.Rows.Count; i++)
{
// to do: format datetime values before printing
for (int j = 0; j < queryDatatable.Columns.Count; j++)
{
workSheet.Cells[(i + 2), (j + 1)] = queryDatatable.Rows[i][j];
}
}
// check fielpath
if (ExcelFilePath != null && ExcelFilePath != "")
{
try
{
workSheet.SaveAs(ExcelFilePath);
excelApp.Quit();
MessageBox.Show("Excel file saved!");
}
catch (Exception ex)
{
throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
+ ex.Message);
}
}
else // no filepath is given, the file opens up and the user can save it accordingly.
{
excelApp.Visible = true;
}
}
catch (Exception ex)
{
MessageBox.Show("There is no data to export. Please check your query/ Contact administrator." + ex.Message);
}
}
#endregion
Here's an extension method to output to any DataTable to a csv (which excel can open)
Imports System.Text
Imports System.IO
Imports System.Runtime.CompilerServices
Module ExtensionMethods
<Extension()> _
Public Sub OutputAsCSV(ByVal dt As DataTable, ByVal filePath As String)
Dim sb As New StringBuilder()
'write column names to string builder
Dim columnNames As String() = (From col As DataColumn In dt.Columns Select col.ColumnName).ToArray
sb.AppendLine(String.Join(",", columnNames))
'write cell value in each row to string builder
For Each row As DataRow In dt.Rows
Dim fields As String() = (From cell In row.ItemArray Select CStr(cell)).ToArray
sb.AppendLine(String.Join(",", fields))
Next
'write string builder to file
File.WriteAllText(filePath, sb.ToString())
End Sub
End Module
Try googling around a little. This is a very common problem and has been asked a lot already. Here's a good answer from this SO question
public static void ExportToExcel<T>(IEnumerable<T> exportData)
{
Excel.ApplicationClass excel = new Excel.ApplicationClass();
Excel.Workbook workbook = excel.Application.Workbooks.Add(true);
PropertyInfo[] pInfos = typeof(T).GetProperties();
if (pInfos != null && pInfos.Count() > 0)
{
int iCol = 0;
int iRow = 0;
foreach (PropertyInfo eachPInfo in pInfos.Where(W => W.CanRead == true))
{
// Add column headings...
iCol++;
excel.Cells[1, iCol] = eachPInfo.Name;
}
foreach (T item in exportData)
{
iRow++;
// add each row's cell data...
iCol = 0;
foreach (PropertyInfo eachPInfo in pInfos.Where(W => W.CanRead == true))
{
iCol++;
excel.Cells[iRow + 1, iCol] = eachPInfo.GetValue(item, null);
}
}
// Global missing reference for objects we are not defining...
object missing = System.Reflection.Missing.Value;
// If wanting to Save the workbook...
string filePath = System.IO.Path.GetTempPath() + DateTime.Now.Ticks.ToString() + ".xlsm";
workbook.SaveAs(filePath, Excel.XlFileFormat.xlOpenXMLWorkbookMacroEnabled, missing, missing, false, false, Excel.XlSaveAsAccessMode.xlNoChange, missing, missing, missing, missing, missing);
// If wanting to make Excel visible and activate the worksheet...
excel.Visible = true;
Excel.Worksheet worksheet = (Excel.Worksheet)excel.ActiveSheet;
excel.Rows.EntireRow.AutoFit();
excel.Columns.EntireColumn.AutoFit();
((Excel._Worksheet)worksheet).Activate();
}
}

OleDbDataAdapter.Update returns rows, but no rows added to Excel spreadsheet

I can add rows to my Excel spreadsheet one row at a time, but it is incredibly slow (1 minute for 400 records, even using Prepare). So, I know the Sql is valid and the DataTable is good.
The code that works:
public void InsertFromDataTable(string strSql, DataTable dtTable, string strTableName)
{
if (m_oleDbHandler == null)
{
m_oleDbHandler = new OleDbHandler(m_strConnection);
}
//Do one row at a time since the DataAdapter did not work
foreach (DataRow drRow in dtTable.Rows)
{
OleDbParmCollection cololedbParameters = new OleDbParmCollection();
foreach (DataColumn dcColumn in dtTable.Columns)
{
OleDbParameter odpParameter = new OleDbParameter("#" + dcColumn.ColumnName, drRow[dcColumn.ColumnName]);
odpParameter.ParameterName = "#" + dcColumn.ColumnName;
odpParameter.DbType = OleDbHandler.GetDbType(dcColumn.GetType());
odpParameter.Size = dcColumn.MaxLength;
odpParameter.SourceColumn = dcColumn.ColumnName;
cololedbParameters.Add(odpParameter);
}
m_oleDbHandler.ExecuteCommand(strSql, cololedbParameters, true);
}
}
}
When I try to do the same thing using a DataAdapter, it says it returns 458 rows, but there are no new rows in the spreadsheet. The code that fails:
//DataAdapter version
OleDbParmCollection cololedbParameters = new OleDbParmCollection();
foreach (DataColumn dcColumn in dtTable.Columns)
{
OleDbParameter odpParameter = new OleDbParameter();
odpParameter.ParameterName = "#" + dcColumn.ColumnName;
odpParameter.OleDbType = OleDbHandler.GetOleDbType(dcColumn.GetType());
odpParameter.DbType = OleDbHandler.GetDbType(dcColumn.GetType());
odpParameter.Size = dcColumn.MaxLength;
odpParameter.SourceColumn = dcColumn.ColumnName;
cololedbParameters.Add(odpParameter);
}
m_oleDbHandler.InsertFromDataTable(strSql, dtTable, cololedbParameters, strTableName);
and then:
public int InsertFromDataTable(string strSql, DataTable dtTable, OleDbParmCollection cololeDbParameters, string strTableName)
{
//Set every row as added so that they will be inserted
foreach (DataRow drRow in dtTable.Rows)
{
drRow.SetAdded();
}
//Update the output table
int intRows = -1;
try
{
OleDbCommand oleDbCommand = new OleDbCommand(strSql, OpenConnection());
foreach (OleDbParameter oleDbParameter in cololeDbParameters)
{
if (oleDbParameter.Value == null)
{
oleDbCommand.Parameters.Add(oleDbParameter.ParameterName, OleDbType.VarChar).Value = DBNull.Value;
}
else if (string.IsNullOrEmpty(oleDbParameter.Value.ToString()))
{
oleDbCommand.Parameters.Add(oleDbParameter.ParameterName, OleDbType.VarChar).Value = DBNull.Value;
}
else
{
oleDbCommand.Parameters.Add(oleDbParameter);
}
}
OleDbDataAdapter odaAdapter = new OleDbDataAdapter(new OleDbCommand("SELECT * FROM " + strTableName, OpenConnection()));
odaAdapter.InsertCommand = oleDbCommand;
odaAdapter.MissingMappingAction = MissingMappingAction.Passthrough;
odaAdapter.MissingSchemaAction = MissingSchemaAction.Error;
odaAdapter.TableMappings.Add(strTableName, dtTable.TableName);
foreach (DataColumn dcColumn in dtTable.Columns)
{
odaAdapter.TableMappings[0].ColumnMappings.Add(dcColumn.ColumnName, dcColumn.ColumnName);
}
intRows = odaAdapter.Update(dtTable);
}
catch (OleDbException ex)
{
LogStackTrace();
LogToDb.LogException(ex, LogToDb.c_strAppError);
LogToDb.LogMessage("OleDb error", "OleDbHandler.InsertFromDataTable error", strSql, LogToDb.c_intErrorLevelOleDb);
CancelTransactionAndClose();
throw;
}
finally
{
CloseConnection();
}
return (intRows);
}
Why would I get intRows = 458, but there are no new rows in the Excel file?
EDIT: I just did a test to see what happens if I export to a Microsoft Access .mdb (instead of Excel), and the results tell me something. I get 458 blank rows. so, I suspect I am getting 458 blank rows in Excel. So, now the question is why the rows are all blank.
Got it -- the error was in the section below. This works well for an ExecuteNonQuery, but lousy when there is no data.
foreach (OleDbParameter oleDbParameter in cololeDbParameters)
{
if (oleDbParameter.Value == null)
{
oleDbCommand.Parameters.Add(oleDbParameter.ParameterName, OleDbType.VarChar).Value = DBNull.Value;
}
else if (string.IsNullOrEmpty(oleDbParameter.Value.ToString()))
{
oleDbCommand.Parameters.Add(oleDbParameter.ParameterName, OleDbType.VarChar).Value = DBNull.Value;
}
else
{
oleDbCommand.Parameters.Add(oleDbParameter);
}
}
The corrected code, which works well with both Access and Excel is:
foreach (OleDbParameter oleDbParameter in cololeDbParameters)
{
oleDbCommand.Parameters.Add(oleDbParameter);
}
There was a second, less serious error. I used
OleDbHandler.GetOleDbType(dcColumn.GetType());
which should have been
OleDbHandler.GetOleDbType(dcColumn.DataType);

Resources