I need to add the column names within a sheet to a combobox
I have tried the following
var pck = new OfficeOpenXml.ExcelPackage();
pck.Load(new System.IO.FileInfo("test.xlsx").OpenRead());
var ws = pck.Workbook.Worksheets[1];
int totalCols = ws.Dimension.End.Column;
for (int i = 1; i <= totalCols; i++)
{
comboBox1.Items.Add( (ws.Column(i).ToString()));
}
}
But this produces a Null Reference Exception.
Why is that happening?
Ensure that you're loading the package correctly and selecting the values correctly:
// Select workbook
var fileInfo = new FileInfo(#"yourfile.xlsx");
// Load workbook
using (var package = new ExcelPackage(fileInfo)) {
// Itterate through workbook sheets
foreach (var sheet in package.Workbook.Worksheets){
// Itterate through each column until final column
for (int i = 1; i <= sheet.Dimension.End.Column; i++) {
comboBox1.Items.Add(sheet.Cells[1, i].Text);
}
}
}
This runs correctly in a new workbook with two sheets and values in the columns of each sheet.
Related
I'm trying to add row to a list object from excel file with empty cells. for some reason getting reference object is not set to instance return null. not sure what could be possible solution for this.
ExcelWorksheet worksheet = package.Workbook.Worksheets["Sheet1"];
var rowcount = worksheet.Dimension.Rows;
for(int row = 2; row <= rowcount; row++)
{
list.Add(new Insured
{
item1 = worksheet.Cells [row, 1].Value.ToString().ToLower().Trim(),
item2 = worksheet.Cells [row, 2].Value.ToString().ToLower().Trim(), //<cell is empty
});
}
I'm currently trying to get specific rows of an Excel file in my code.
I get the data of my Excel file with this code:
FileInfo existingFile = new FileInfo(local_in_file_path);
using (ExcelPackage package = new ExcelPackage(existingFile))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
int colCount = worksheet.Dimension.End.Column; //get Column Count
int rowCount = worksheet.Dimension.End.Row; //get row count
List<string> testlist = new List<string>();
List<string> articlelist = new List<string>();
for (int row = 1; row <= rowCount; row++)
{
for (int col = 1; col <= colCount; col++)
{
testlist.Add(worksheet.Cells[row, col].Value?.ToString().Trim());
foreach (var i in testlist)
{
if (articlelist.Contains(i))
{
continue;
}
else
{
articlelist.Add(i);
}
}
}
}
foreach (var article in articlelist)
{
var rows = worksheet.Row().Where(n => n = article); //doesnt work
}
In the foreach loop I want all rows, in which the specific article occurs. How can I do this?
Be careful because when you add something to testlist you are picking only 1 cell everytime (so if your excel file is structured like "1 row has 'article name' , 'description' ecc you are running through every col in every row so it's pretty inefficient, if you could only provide an example of your excel file we can try to help, and does that foreach create an exception or something else?
This code is working fine but i want to do that i have 3 sheets in excel file and all sheets
have different columns size , suppose first sheet have 5 columns second have 3 and third have
7 so on the basis of sheets i want to insert new row. Like if first sheet have 5 columns then data
insert only in 5 columns if second have 3 then only 3 values insert like that. So, can any one guide
me to do that.
using(FileStream fs = new FileStream(filepath, Filemode.Open, FileAccess.ReadWrite,
FileShare.ReadWrite))
{
SpreadSheetDocument document = SpreadsheetDocument.Open(fs, false);
SharedStringTable sharedStringTable =
document.WorkbookPart.SharedStringTablePart.SharedStringTable;
string cellValue = null;
foreach (WorksheetPart worksheetPart in document.WorkbookPart.WorksheetParts.Reverse())
{
int cnt = document.WorkbookPart.WorksheetParts.count();
foreach (SheetData sheetData in worksheetPart.Worksheet.Elements<SheetData>())
{
if (sheetData.HasChildren)
{
foreach (Row row in sheetData.Elements<Row>())
{
foreach (Cell cell in row.Elements<Cell>())
{
Row row = new Row();
row.Append(ConstructCell("firstvalue",CellValues.String));
sheetData.AppendChild(row);
WorksheetPart.Worksheet.Save();
}
}
}
}
}
}
document.Close();
Public static Cell ConstructCell(string value , CellValues datatype)
{
return new Cell(){CellValue = new CellValue(value),DataType = new EnumValue<CellValues>
(datatype)};
}
I done it.
//Replace this from
Row row = new Row();
row.Append(ConstructCell("firstvalue",CellValues.String));
sheetData.AppendChild(row);
WorksheetPart.Worksheet.Save();
//To this one ::
var rows = sheetData.Elements<Row>;
int rwCnt = rows.Count();
var clCnt = rows.First().ChildElements.Count();
for(int i = 0; i < 1 ; i++)
{
Row row = new Row();
for(j = 0; j < clCnt; j++)
{
row.Append(
ConstructCell("firstvalue",CellValues.String)
)
}
sheetData.AppendChild(row);
WorksheetPart.Worksheet.Save();
}
I'm trying to build a wrapper for SpreadsheetLight that returns a DataSet from any .xlsx document passed through it. However, I seem to be having a problem with DataRows not being added to a temporary DataTable.
Here's part of the code that parses a worksheet and generates a DataTable from it:
public DataSet ReadToDataSet(string fileName)
{
using (var wb = new SLDocument(fileName))
{
var set = new DataSet(GenerateTitle(wb.DocumentProperties.Title));
foreach (var wsName in wb.GetWorksheetNames())
{
var ws = wb.SelectWorksheet(wsName);
// Select worksheet returns a bool, so if it comes back false, try the next worksheet instead.
if (!ws) continue;
// Statistics gives indecies of the first and last data cells
var stats = wb.GetWorksheetStatistics();
// Create a new DataTable for each worksheet
var dt = new DataTable(wsName);
//var addDataColumns = true;
for (var colIdx = stats.StartColumnIndex; colIdx < stats.EndColumnIndex; colIdx++)
dt.Columns.Add(colIdx.ToString(), typeof(string));
// Scan each row
for (var rowIdx = stats.StartRowIndex; rowIdx < stats.EndRowIndex; rowIdx++)
{
//dt.Rows.Add();
var newRow = dt.NewRow();
// And each column for data
for (var colIdx = stats.StartColumnIndex; colIdx < stats.EndColumnIndex; colIdx++)
{
//if (addDataColumns)
// dt.Columns.Add();
newRow[colIdx - 1] = wb.GetCellValueAsString(rowIdx, colIdx);
//if (colIdx >= stats.EndColumnIndex)
// addDataColumns = false;
}
dt.Rows.Add(newRow);
}
set.Tables.Add(dt);
}
// Debug output
foreach (DataRow row in set.Tables[0].Rows)
{
foreach (var output in row.ItemArray)
{
Console.WriteLine(output.ToString());
}
}
return set;
}
}
Note: SpreadsheetLight indicies start from 1 instead of 0;
Now, I've tried replacing dt.Rows.Add() with new object[stats.EndColumnIndex -1];, as well as a temporary variable from var newRow = dt.NewRow(); and then passing them into the DataTable afterwards, but still get the same end result. The row objects are populating correctly, but aren't transferring to the DataTable at the end.
When you explore the object during runtime, it shows the correct number of rows and columns in the relevant properties. But when you open it up in the DataVisualiser you can only see the columns, no rows.
I must be missing something obvious.
Update
I looped through the resulting table and output the values to the console as a test. All the correct values appear, but the visualiser remains empty:
I guess the question now is, why would there be no data in the visualiser when there is valid data in the DataTable?
Update 2
Added the full method for reference, including a simple set of for loops to loop through all rows and columns in the first DataTable. Note: I also experimented with pulling the column creation out of the loop and even setting the datatypes. Made no difference. Commented code shows the original.
Ok, turns out the problem was most likely from the columns being added. Either there were too many columns for the visualiser to handle (1024) which I find hard to believe, or there was a bug in visual studio that's randomly corrected itself.
There's also a bug in SpreadsheetLight that lists all columns as having data when you call GetWorksheetStatistics(); so I've used a workaround that uses the maximum number of total cells available OR the stats.NumberOfColumns, whichever is the smallest.
Either way, the below code now functions.
public DataSet ReadToDataSet(string fileName)
{
using (var wb = new SLDocument(fileName))
{
var set = new DataSet(GenerateTitle(wb.DocumentProperties.Title));
foreach (var wsName in wb.GetWorksheetNames())
{
var ws = wb.SelectWorksheet(wsName);
// Select worksheet returns a bool, so if it comes back false, try the next worksheet instead.
if (!ws) continue;
// Statistics gives indecies of the first and last data cells
var stats = wb.GetWorksheetStatistics();
// There is a bug with the stats columns. Take the total number of elements available or the columns from the stats table, whichever is the smallest
var newColumnIndex = stats.NumberOfCells < stats.NumberOfColumns
? stats.NumberOfCells
: stats.NumberOfColumns;
// Create a new DataTable for each worksheet
var dt = new DataTable(wsName);
var addDataColumns = true;
// Scan each row
for (var rowIdx = stats.StartRowIndex; rowIdx < stats.EndRowIndex; rowIdx++)
{
var newRow = dt.NewRow();
// And each column for data
for (var colIdx = stats.StartColumnIndex; colIdx < newColumnIndex; colIdx++)
{
if (addDataColumns)
dt.Columns.Add();
newRow[colIdx - 1] = wb.GetCellValueAsString(rowIdx, colIdx);
}
addDataColumns = false;
dt.Rows.Add(newRow);
}
set.Tables.Add(dt);
}
return set;
}
}
Hopefully someone else finds this as a useful reference in the future, either for SpreadsheetLight or DataVisualiser in Visual Studio. If anyone know's of any limits for the visualiser, I'm all ears!
How to target Cell if I know its content (there are no duplicates in the xlsx document) using Office Open XML?
I mean I have xlsx sheet (template) and somewhere in it placed my "variable". For example "<<_time>>". I want to find that element (by "variable" name) and change the cell value (current time in this case).
Basic code:
FileInfo newFile = new FileInfo(#"...");
FileInfo template = new FileInfo(#"...");
using (ExcelPackage xlPackage = new ExcelPackage(newFile, template))
{
ExcelWorksheet worksheet = xlPackage.Workbook.Worksheets.First();
//need target Cell by it's value (must use for-loop?)
//worksheet.Cells[...].Value = "...";
xlPackage.Save();
}
Ok, I solved it by classic loop.
var start = worksheet.Dimension.Start;
var end = worksheet.Dimension.End;
for (int row = start.Row; row <= end.Row; row++)
{
for (int col = start.Column; col <= end.Column; col++)
{
string cellValue = worksheet.Cells[row, col].Text.ToString();
if (cellValue == "<<_time>>")
{
worksheet.Cells[row, col].Value = "..";
}
}
}