My project has 2 console applications.
First application is writing data to the "first sheet" of an existing excel file (xlsx). The same excel file has a "second sheet" which is pretty huge and is using several formulas which are based on the data of the first sheet.
I am using the following code for writing the data to the first sheet:
public void WriteExcel(string InvoiceNo, string InvoiceDate, ...., int rowNumber)
{
using (ExcelPackage excelPackage = new ExcelPackage(this.excelFilePath))
{
ExcelWorksheet firstWorksheet = excelPackage.Workbook.Worksheets.First();
firstWorksheet.Cells[rowNumber, 1].Value = (rowNumber - 2).ToString();
firstWorksheet.Cells[rowNumber, 2].Value = InvoiceNo;
firstWorksheet.Cells[rowNumber, 3].Value = InvoiceDate;
.
.
excelPackage.Save();
}
}
The above code is working completely fine.
Second application is fetching data from the second sheet of this excel file and here I am facing an strange issue.
The application, in the first place, is not picking up the data from the second sheet. But if I am opening the same excel file and closing it after saving it (by pressing Ctrl + S), then the application is fetching data properly.
I am using the following code to fetch the data:
string FilePath = #"file path";
foreach (string file in Directory.EnumerateFiles(FilePath, "*.xlsx"))
{
FileInfo fileInfo = new FileInfo(file);
ExcelPackage package = new ExcelPackage(fileInfo);
ExcelWorksheet excelSheet = package.Workbook.Worksheets[2];
int colCount = excelSheet.Dimension.End.Column;
int rowCount = excelSheet.Dimension.End.Row;
for (int col = 7; col < colCount; col++)
{
if (excelSheet.Cells[27, col].Value != "" && excelSheet.Cells[27, col].Value != null && excelSheet.Cells[27, col].Value.ToString() != "NAN")
{
Console.WriteLine("Data found!.. " + excelSheet.Cells[27, col].Value);
Console.ReadLine();
}
}
}
Please help me on this.
Related
I'm trying to write code in C# WinForms that allows a user to select a directory tree, and extract all of the table data from a word document into an excel file. Presently, the code compiles and you can select your directories, etc, but once it begins to iterate through the loop for each table it crashes.
The program successfully opens the first word file and writes the first excel file (table_1_whatever.xlsx) and saves it in the destination folder. However, on the second table in the same file I get this error on this line of code:
worksheet.Cells[row, col] = objExcelApp.WorksheetFunction.Clean(table.Cell(row, col).Range.Text);
System.Runtime.InteropServices.COMException: 'The requested member of the collection does not exist.'
I can't seem to figure out why it doesn't exist. Each time it goes through the foreach loop it should be creating a new worksheet, but it doesn't appear to be working. Any insight, examples, or suggestions are welcome!
Code:
private void WordRunButton_Click(object sender, EventArgs e)
{
var excelApp = new excel.Application();
excel.Workbooks workbooks = excelApp.Workbooks;
var wordApp = new word.Application();
word.Documents documents = wordApp.Documents;
wordApp.Visible = false;
excelApp.Visible = false;
string[] fileDirectories = Directory.GetFiles(WordSourceBox.Text, "*.doc*",
SearchOption.AllDirectories);
foreach (var item in fileDirectories)
{
word._Document document = documents.Open(item);
int tableCount = 1;
foreach (word.Table table in document.Tables)
{
if (table.Cell(1, 1).ToString() != "Doc Level")
{
string wordFile = item;
appendName = Path.GetFileNameWithoutExtension(wordFile) + "_Table_" + tableCount + ".xlsx";
var workbook = excelApp.Workbooks.Add(1);
excel._Worksheet worksheet = (excel.Worksheet)workbook.Sheets[1];
for (int row = 1; row <= table.Rows.Count; row++)
{
for (int col = 1; col <= table.Columns.Count; col++)
{
var cell = table.Cell(row, col);
var range = cell.Range;
var text = range.Text;
var cleaned = excelApp.WorksheetFunction.Clean(text);
worksheet.Cells[row, col] = cleaned;
}
}
workbook.SaveAs(Path.Combine(WordOutputBox.Text, Path.GetFileName(appendName)), excel.XlFileFormat.xlWorkbookDefault);
workbook.Close();
Marshal.ReleaseComObject(workbook);
}
else
{
WordOutputStreamBox.AppendText(String.Format("Table {0} ignored\n", tableCount));
}
WordOutputStreamBox.AppendText(appendName + "\n");
tableCount++;
}
document.Close();
Marshal.ReleaseComObject(document);
WordOutputStreamBox.AppendText(item + "\n");
}
WordOutputStreamBox.AppendText("\nAll files parsed");
excelApp.Application.Quit();
workbooks.Close();
excelApp.Quit();
WordOutputStreamBox.AppendText("\nExcel files closed");
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelApp);
WordOutputStreamBox.AppendText("\nExcel files released");
wordApp.Application.Quit();
wordApp.Quit();
WordOutputStreamBox.AppendText("\nWord files have been quit");
Marshal.ReleaseComObject(documents);
Marshal.ReleaseComObject(wordApp);
WordOutputStreamBox.AppendText("\nWord files have been released\n");
}
Edit 1:(Sorry for posting in the wrong place the first time!)
Ok, so the problem has been isolated...
The code logic of the code was fine, and the table was in fact there. The issue is that the second table of these files has a set of split cells in it, so, when it reaches the cell that contains it, the program crashes.
As a temp fix, I have just set it to ignore the table if the header == whatever. Does anyone know of a solution that actually allows to extract this data though?
My ideal is : open some .csv files (5 or 6 or more) and add 2 new columns to all opened files and finally save it. Here is my code
OpenFileDialog fopen = new OpenFileDialog();
fopen.Multiselect = true;
fopen.Filter = "(All type)|*.*";
fopen.ShowDialog();
if (fopen.FileName != null)
{
Excel.Application app = new Excel.Application();
Excel.Workbook wb = app.Workbooks.Open(fopen.FileName);
Excel.Worksheet sheet = wb.Sheets[1];
Excel.Range range = sheet.UsedRange;
int column = range.Columns.Count;
int row = range.Rows.Count;
textBox1.Text = fopen.FileName;
//textBox2.Text = row.ToString();
//textBox3.Text = column.ToString();
range.Cells.set_Item(1, column + 1, "Mo_stMoC");
range.Cells.set_Item(1, column + 2, "Mo_stMoCCpl");
for (int i = 2; i <= row; i++)
{
range.Cells.set_Item(i, column + 1, "0");
range.Cells.set_Item(i, column + 2, "0");
}
wb.Save();
wb.Close();
app.Workbooks.Close();
app.Quit();
}
The problem is, when I open the files and it just adding 2 columns in the first .csv file.
I'm new to C#, so what am I doing wrong here?
you are opening multiple files, so loop through fopen.FileNames instead of just using fopen.FileName
foreach (String file in fopen.FileNames)
{
//do your thing
//edit
}
Additionally it is better to filter only csv files instead of all.
fopen.Filter = "CSV Files (*.csv)|*.csv";
I am desperately trying to add multiple items from an excel sheet into a listview using c#. I have looked all over the Internet for a working solution but still no result.
I would like to ask anybody who knows about c#'s listview for an helping hand...
Thanks in advance
code so far:-
public void InitializeListView(string path) {
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook sheet = excel.Workbooks.Open(path);
Microsoft.Office.Interop.Excel.Worksheet wx = excel.ActiveSheet as Microsoft.Office.Interop.Excel.Worksheet;
int count = 0;
int row = 0;
int col = 0;
Excel.Range userrange = wx.UsedRange;
count = userrange.Rows.Count;
statusBar1.Panels[1].Text = "Amount: " + count;
for (row = 1; row <= count; row++) {
for (col = 1; col <= 4; col++) {
listView1.Items.Add(wx.Cells[row, col].Value2);
listView1.Items.Add(wx.Cells[row, col].Value2);
listView1.Items.Add(wx.Cells[row, col].Value2);
listView1.Items.Add(wx.Cells[row, col].Value2);
}
}
sheet.Close(true, Type.Missing, Type.Missing);
excel.Quit();
}//------------------ end of InitializeListView -------------------------
This might be help you please see https://www.codeproject.com/Questions/460391/Retrieve-datas-from-Excel-Sheet-to-Listview
This is a simple method. Please look if it helps you.
1. Convert the Excel file in to .csv and Store it in the a Path
2. Take the data from .csv file to list.
3. Delete the .csv file once all data is loaded in List<>.
To Read from .csv
string filepath = "D:\\sample.csv";
var lineCount = File.ReadAllLines(#"D:\\sample.csv").Length;
int TotalLines = Int32.Parse(lineCount.ToString());
StreamReader sr = new StreamReader(filepath);
string line;
List<string> lstSample = new List<string>();
while ((line = sr.ReadLine()) != null)
{
lstSample = line.Split(',').ToList();
}
I've found how to read first line from Excel file with specific sheet name, but in my case I have to read first line of the first sheet.
How can I realize that or I have to use CSV instead of XLS?
Did you take a look at the EPPlus library? It makes very easy to work with excel files.
Here is how you would do that using EPPlus:
FileInfo existingFile = new FileInfo("yourfilepathname");
using (var package = new ExcelPackage(existingFile))
{
ExcelWorkbook workbook = package.Workbook;
if (workbook != null && workbook.Worksheets.Count > 0)
{
//Gets the first worksheet. You can use index also to select your worksheet.
ExcelWorksheet worksheet = workbook.Worksheets.First();
int rowIndex = 0;
int colIndex = 0;
//To get the first cell:
var cellValue = worksheet.Cells[rowIndex, colIndex].Value;
//YOU CAN ALSO DO A LOOP TO GET ALL VALUES FROM THE FIRST ROW.
}
}
NPOI is another good option and it can handle XLS files too.
Here's a snippet of NPOI code:
HSSFWorkbook _hssfworkbook = new HSSFWorkbook(OpenFileStream(filePath));
//Getting the sheet
_currentSheet = _hssfworkbook.GetSheetAt(0);
//Getting the row:
_row = CurrentSheet.GetRow(0);
//Getting the cell
_cell = _row.GetCell(0);
Have you considered SpreadsheetLight? Here's how you do it:
SLDocument sl = new SLDocument("YourExcelFile.xlsx", "TheSheetName");
string FirstLine = sl.GetCellValueAsString("A1");
sl.CloseWithoutSaving();
Disclaimer: I wrote SpreadsheetLight.
well i have to creat just one excel file and 2 sheets both are fill using a 2 diferent DataTable, it gives the name the user only has to click save, the next code allows me to seend one datatable to one sheet (i am using C#, asp.net, and NOT using Visual Studio, i am writing in the Notepad my code):
string name2="Centroids";
HttpContext context = HttpContext.Current;
context.Response.Clear();
foreach (System.Data.DataRow row in _myDataTable2.Rows)
{
for (int i = 0; i < _myDataTable2.Columns.Count; i++)
{
context.Response.Write(row[i].ToString().Replace(",", string.Empty) + ",");
}
context.Response.Write(Environment.NewLine);
}
context.Response.ContentType = "text2/csv";
context.Response.AppendHeader("Content-Disposition", "attachment; filename=" + name2 + ".csv");
but i have no idea how to creat the second sheet and use the second DataTable, any ideas of how to find a solution, this way the user has only to save and donwload only one document and not save as many DataTable are in the programa
You probably want to explore the possibility of using EPPlus. In my experience, using Response object has lot of constraints and take too much development effort to generate Excel file.
Url:
http://epplus.codeplex.com/
You should use open source libraries for generating native excel files, there is no way you can create two sheets with csv.
Use NPOI (xls) or / and EPPlus (xlsx) and fully control your excel export, in this answer https://stackoverflow.com/a/9569827/351383 you can see example of creating excel file from DataTable with EPPlus. You can edit that method to accept DataTable list and create new sheets for each table, it's simple, just :
ExcelPackage pack = new ExcelPackage();
ExcelWorksheet ws = pack.Workbook.Worksheets.Add(sheetName);
public bool LlenarExcelxlsx(List<DatosEntidad> listaOrigen)
{
bool exito = false;
string[] tipoLista = { "A", "B", "C" };
string nombreArchivo = #"D:\prueba.xlsx";
IWorkbook wb = new XSSFWorkbook();
using (FileStream fileData = new FileStream(nombreArchivo, FileMode.Create, FileAccess.Write))
{
for (int k = 0; k < tipoLista.Length; k++)
{
List<DatosEntidad> listaDestino = listaOrigen
.Where(c => c.tipo == tipoLista[k]).ToList();
DataTable dt = ToDataTable(listaDestino);
ISheet sheetx = wb.CreateSheet("Res_" + tipoLista[k] + k);
ICreationHelper cH = wb.GetCreationHelper();
for (int i = 0; i < dt.Rows.Count; i++)
{
IRow row = sheetx.CreateRow(i);
for (int j = 0; j < 13; j++)
{
ICell cell = row.CreateCell(j);
cell.SetCellValue(cH.CreateRichTextString(dt.Rows[i].ItemArray[j].ToString()));
}
}
}
wb.Write(fileData);
exito = true;
}
return exito;
}