C# application terminates when writing data to excel worksheet - c#

I am trying to write data in excel work sheet using .Net. However, for some reason whole application terminates (No exception, no warning, no message) when row counter increases to around 900. Whereas, there could be up to 10000 entries.
Furthermore it also terminates if i put a sleep statement, when filling contents. I suspect that there is some sort of timeout associated with excel objects?
Any Ideas what could be causing this? Thanks
Here is the main function -
public void ProduceExcelReport(string reportDirPath, List<MedlineRecord> medlineRecords, List<AccessionRecord> accessionRecords,
List<string> dataBanksOfInterest, bool overwrite)
{
Excell.Application excelApp = null;
Excell.Workbooks excelWorkBooks = null;
Excell.Workbook excelWorkBook = null;
Excell.Sheets worksheets = null;
Excell.Worksheet overAllWorkSheet = null;
Excell.Worksheet parsingWorkSheet = null;
Excell.Worksheet errorWorkSheet = null;
Excell.Worksheet noCitationsSheet = null;
Excell.Worksheet outOfScopeWorksheet = null;
try
{
excelApp = new Excell.Application();
string fullReportPath = Path.Combine(reportDirPath, ReportName);
if (File.Exists(fullReportPath))
{
if (!overwrite)
{
Logger.Warning(string.Format("File {0} already exists. Skipping report production." +
"You can change behaviour by editing OverwriteFilesWithNameConflict tag in settings",
fullReportPath));
return;
}
Logger.Warning(string.Format("File {0} already exists. Overwritting old report." +
"You can change behaviour by editing OverwriteFilesWithNameConflict tag in settings",
fullReportPath));
}
// Initialise
excelApp.DisplayAlerts = false;
object misValue = System.Reflection.Missing.Value;
excelWorkBooks = excelApp.Workbooks;
excelWorkBook = excelWorkBooks.Add(misValue);
worksheets = excelWorkBook.Worksheets;
overAllWorkSheet = (Excell.Worksheet) worksheets.Item[1];
parsingWorkSheet = (Excell.Worksheet) worksheets.Item[2];
errorWorkSheet = (Excell.Worksheet) worksheets.Item[3];
noCitationsSheet = (Excell.Worksheet) worksheets.Add();
outOfScopeWorksheet = (Excell.Worksheet)worksheets.Add();
// Filling contents
FillOverallReportContents(ref overAllWorkSheet, accessionRecords);
FillMedlineParsingReportContents(ref parsingWorkSheet, medlineRecords, dataBanksOfInterest); // <- Terminates when writting contents
FillErrorReportContents(ref errorWorkSheet, medlineRecords);
FillNoCitationReportContents(ref noCitationsSheet, medlineRecords);
FillOutOfScopeReportContents(ref outOfScopeWorksheet, medlineRecords, dataBanksOfInterest);
excelWorkBook.SaveAs(fullReportPath);
excelWorkBook.Close(true, misValue, misValue);
excelApp.Quit(); // Quiting excel app
Logger.Info(string.Format("Excel report at {0} was successfully created", fullReportPath));
}
catch (Exception e)
{
Logger.ExceptionError("Exception occured when trying to write Excel Report", e);
}
finally
{
if (overAllWorkSheet != null) Marshal.ReleaseComObject(overAllWorkSheet);
if (parsingWorkSheet != null) Marshal.ReleaseComObject(parsingWorkSheet);
if (noCitationsSheet != null) Marshal.ReleaseComObject(noCitationsSheet);
if (errorWorkSheet != null) Marshal.ReleaseComObject(errorWorkSheet);
if (outOfScopeWorksheet != null) Marshal.ReleaseComObject(outOfScopeWorksheet);
if (worksheets != null) Marshal.ReleaseComObject(worksheets);
if (excelWorkBook != null) Marshal.ReleaseComObject(excelWorkBook);
if (excelWorkBooks != null) Marshal.ReleaseComObject(excelWorkBooks);
if (excelApp != null) Marshal.ReleaseComObject(excelApp);
}
}
Here is one of the functions that fills worksheet contents
private void FillMedlineParsingReportContents(ref Excell.Worksheet excelWorkSheet, List<MedlineRecord> medlineRecords, List<string> dataBanksOfInterest)
{
// Write the worksheet contents
AddFirstRow(ref excelWorkSheet);
excelWorkSheet.Name = "Medline XML Parsing Summary";
excelWorkSheet.Cells[2, 6] = string.Format("Total articles: {0}", medlineRecords.Count);
excelWorkSheet.Cells[3, 6] = string.Format("Total number dataBank list tags: {0}", (from element in medlineRecords
where element.DataBanksDict.Count > 0
select element).Count());
excelWorkSheet.Cells[4, 6] = string.Format("Total number dataBank tags: {0}", (from element in medlineRecords
select element.DataBanksDict.Count).Sum());
excelWorkSheet.Cells[5, 6] = string.Format("Total number accession tags: {0}", (from element in medlineRecords
select element.GetAccessionRecords().Count).Sum());
int i = 2;
foreach (MedlineRecord record in Utilities.FilterOutMedlineRecords(medlineRecords, dataBanksOfInterest))
{
foreach (AccessionRecord accessionRecord in record.GetAccessionRecords())
{
excelWorkSheet.Cells[i, 1] = accessionRecord.BankName;
excelWorkSheet.Cells[i, 2] = accessionRecord.AccessionId;
excelWorkSheet.Cells[i, 3] = accessionRecord.PMID;
excelWorkSheet.Cells[i, 4] = accessionRecord.FileName;
i++;
// Terminates when I reaches around 800-900
Console.WriteLine(i);
}
}
}

Related

DataGridViewS export to excel sheetS

I want to export all my DataGridViews in one Excell document.
For every DataGridView there shoud be a own sheet in the Excell File.
But with my code i only recive the Error: System.Runtime.InteropServices.COMException: HRESULT: 0x800A03EC"
I think there is something wrong with my parameters.
private void exportToExcellButton_Click(object sender, EventArgs e)
{
SaveFileDialog saveFileD = new SaveFileDialog();
string fileName = truckListBox.SelectedItem.ToString() + "__" + DateTime.Now.ToShortDateString();
saveFileD.InitialDirectory = #"C:/TML/";
saveFileD.FileName = fileName;
if (!Directory.Exists(#"C:/TML/"))
Directory.CreateDirectory(#"C:/TML/");
List<DataGridView> dataGridViews = getAllDataGridViews();
Microsoft.Office.Interop.Excel.Application app;
Microsoft.Office.Interop.Excel.Workbook book;
Microsoft.Office.Interop.Excel.Worksheet sheet;
app = new Excel.Application();
app.Visible = true;
book = app.Workbooks.Add(System.Reflection.Missing.Value);
foreach (var grid in dataGridViews)
{
int count = book.Worksheets.Count;
sheet = (Worksheet)book.Sheets.Add(Type.Missing, book.Worksheets[count], Type.Missing, Type.Missing);
sheet.Name = grid.Name.ToString().Remove(0, 13);
int cMin = 0, rMin = 0;
int c = cMin, r = rMin;
// Set Headers
foreach (DataGridViewColumn column in grid.Columns)
{
//Here appears the Error: System.Runtime.InteropServices.COMException: HRESULT: 0x800A03EC"
sheet.Cells[r, c] = column.HeaderText;
c++;
}
sheet.Range[sheet.Cells[r, cMin], sheet.Cells[r, c]].Font.Bold = true;
sheet.Range[sheet.Cells[r, cMin], sheet.Cells[r, c]].VerticalAlignment = Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
// Set Rows
foreach (DataGridViewRow row in grid.Rows)
{
r++;
c = cMin;
// Set Cells
foreach (DataGridViewCell item in row.Cells)
{
sheet.Cells[r, c++] = item.Value;
}
}
}
book.Save();
book.Close();
app.Quit();
}
Spended allready days into it and cant get it work.
Thx for your Help!
EDIT: Fixed one error to get to the new one.
There are a few problems you may have with the posted code. Therefore, I will break them down.
For starters, it appears you are using a SaveFileDialog however I do not see where it is being used. The code sets the InitalDirectory and FileName, but it is never used. This is not that important as a dialog is not really needed, however the way the code is getting the file name is going to have some problems. The line of code…
string fileName = truckListBox.SelectedItem.ToString() + "__" + DateTime.Now.ToShortDateString();
is going to have problems if you try to save the file name because the string returned from DateTime.Now.ToShortDateString() is going to be in a format like “2019\11\26”… Obviously the “\” characters are going to be interpreted as a path (folder) and will most likely fail when the code tries to save the file. Creating a method that returns a string that uses some other character should be easy to fix this.
Next is the fact that Excel files are NOT zero based on their rows and columns. Therefore, setting the initial Excel row column variables (int c = 0, r = 0;) will fail on the first try. These values should be one (1).
Another problem is on the line…
book.Save();
Is most likely going to save the file to the users “Documents” folder using the file name of “Book1.xlsx.” When saving the file you need to supply the complete path and file name which as stated earlier does not appear to be used.
Lastly, anytime you use “COM” objects such as Excel apps, workbooks and worksheets, it is very important for the code to “RELEASE” the com objects your code creates before you exit the program. In the current posted code, it is highly likely that there are lingering “Excel” resources still running. Therefore, to avoid leaking resources, it is important for your code to release the com objects it creates.
In my example below the code to release the resources is in the finally clause of the try/catch/finally statement.
private void button1_Click(object sender, EventArgs e) {
//SaveFileDialog saveFileD = new SaveFileDialog();
//string fileName = truckListBox.SelectedItem.ToString() + "__" + DateTime.Now.ToShortDateString();
string fileName = #"C:\Users\John\Desktop\Grr\TestExcelFile" + "__" + DateTime.Now.Year + "_" + DateTime.Now.Month;
//saveFileD.InitialDirectory = #"C:\Users\John\Desktop\Grr\";
//saveFileD.FileName = fileName;
//if (!Directory.Exists(#"C:/TML/"))
// Directory.CreateDirectory(#"C:/TML/");
//List<DataGridView> dataGridViews = getAllDataGridViews();
List<DataGridView> dataGridViews = getGrids();
Microsoft.Office.Interop.Excel.Application app = null;
Microsoft.Office.Interop.Excel.Workbook book = null;
Microsoft.Office.Interop.Excel.Worksheet sheet = null;
app = new Microsoft.Office.Interop.Excel.Application();
app.Visible = true;
book = app.Workbooks.Add(System.Reflection.Missing.Value);
try {
foreach (var grid in dataGridViews) {
int count = book.Worksheets.Count;
//sheet = (Microsoft.Office.Interop.Excel.Worksheet)book.Sheets.Add(Type.Missing, book.Worksheets[count], Type.Missing, Type.Missing);
sheet = (Microsoft.Office.Interop.Excel.Worksheet)book.Worksheets.Add();
//sheet.Name = grid.Name.ToString().Remove(0, 13);
sheet.Name = grid.Name.ToString();
int cMin = 1, rMin = 1;
int c = cMin, r = rMin;
// Set Headers
foreach (DataGridViewColumn column in grid.Columns) {
//Here appears the Error: System.Runtime.InteropServices.COMException: HRESULT: 0x800A03EC"
sheet.Cells[r, c] = column.HeaderText;
c++;
}
sheet.Range[sheet.Cells[r, cMin], sheet.Cells[r, c]].Font.Bold = true;
sheet.Range[sheet.Cells[r, cMin], sheet.Cells[r, c]].VerticalAlignment = Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
// Set Rows
foreach (DataGridViewRow row in grid.Rows) {
r++;
c = cMin;
// Set Cells
foreach (DataGridViewCell item in row.Cells) {
sheet.Cells[r, c++] = item.Value;
}
}
}
book.SaveAs(fileName, Type.Missing, Type.Missing, Type.Missing);
book.Close();
app.Quit();
}
catch (Exception ex) {
MessageBox.Show("Error writing to excel: " + ex.Message);
}
finally {
if (sheet != null)
Marshal.ReleaseComObject(sheet);
if (book != null)
Marshal.ReleaseComObject(book);
if (app != null)
Marshal.ReleaseComObject(app);
}
}
Hope this helps.
Simply Make a method and pass DataGridView
using Excel = Microsoft.Office.Interop.Excel;
public void ete(DataGridView dgv)//ExportToExcel
{
// Creating a Excel object.
Excel._Application excel = new Excel.Application();
Excel._Workbook workbook = excel.Workbooks.Add(Type.Missing);
Excel._Worksheet worksheet = null;
excel.Columns.ColumnWidth = 20;
try
{
worksheet = workbook.ActiveSheet;
worksheet.Name = "ExportedFromDatGrid";
int cellRowIndex = 1;
int cellColumnIndex = 1;
//Loop through each row and read value from each column.
for (int i = -1; i < dgv.Rows.Count; i++)
{
for (int j = 0; j < dgv.Columns.Count; j++)
{
// Excel index starts from 1,1. As first Row would have the Column headers, adding a condition check.
if (cellRowIndex == 1)
{
worksheet.Cells[cellRowIndex, cellColumnIndex] = dgv.Columns[j].HeaderText;
}
else
{
worksheet.Cells[cellRowIndex, cellColumnIndex] = dgv.Rows[i].Cells[j].Value.ToString();
}
cellColumnIndex++;
}
cellColumnIndex = 1;
cellRowIndex++;
}
//Getting the location and file name of the excel to save from user.
SaveFileDialog saveDialog = new SaveFileDialog();
saveDialog.Filter = "Excel files (*.xlsx)|*.xlsx|All files (*.*)|*.*";
saveDialog.FilterIndex = 2;
if (saveDialog.ShowDialog() == DialogResult.OK)
{
workbook.SaveAs(saveDialog.FileName.ToString());
MessageBox.Show("Export Successful");
}
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
excel.Quit();
workbook = null;
excel = null;
}
}
Now Call Method
ete(datagridview1);

Disable Winform application cache

I developed winform application that read from excel and transform it to text files.
I used Microsoft.Office.Interop.Excel library in order to work with Excel.
Here is my code:
private Excel.Application excel = null;
private Excel.Sheets sheets = null;
private Excel.Workbook excelWorkbook = null;
private Excel.Workbooks excelWorkbooks = null;
private Excel._Worksheet worksheet = null;
private Excel.Range usedRange = null;
public ExcelFacade() { }
public ExcelFacade(string fileName)
{
excel = new Excel.Application();
excelWorkbooks = excel.Workbooks;
excelWorkbook = excelWorkbooks.Open(fileName, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
sheets = excelWorkbook.Sheets;
}
After I finished work with Excel I call next method (from here):
public void Dispose()
{
foreach (Microsoft.Office.Interop.Excel.Worksheet sheet in sheets)
{
while (Marshal.ReleaseComObject(sheet) != 0) { }
}
excelWorkbook.Close();
excelWorkbooks.Close();
excel.Quit();
var chromeDriverProcesses = Process.GetProcesses().
Where(pr => pr.ProcessName.ToLower().Contains("excel"));
foreach (var process in chromeDriverProcesses)
{
process.Kill();
}
//while (Marshal.ReleaseComObject(usedRange) != 0) { }
//while (Marshal.ReleaseComObject(worksheet) != 0) { }
while (Marshal.ReleaseComObject(sheets) != 0) { }
while (Marshal.ReleaseComObject(excelWorkbook) != 0) { }
while (Marshal.ReleaseComObject(excelWorkbooks) != 0) { }
//while (Marshal.ReleaseComObject(excel.Application) != 0)
//{ }
while (Marshal.ReleaseComObject(excel) != 0) { }
usedRange = null;
worksheet = null;
excelWorkbook = null;
excelWorkbooks = null;
sheets = null;
excel = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
However, if I change excel and rerun my application, the updated excel is not taken by application and it looks like it read from old excel. Such behavior is look like caching and I have no idea how to disable it.
The aforementioned is strengthened by the fact that if I change something in my code, e.g. white space, and rebuild the application, it works brilliant and take right Excel file.
Any suggestions?
As #vbnet3d said, using ClosedXML library solves all problems

create an excel file in C# with a file save dialog feature . The excel process will be keep running forever in the background

I am new to C#, working on a project recently. having problem about saving the excel file part. I want the user to be able to choose where to save the file (BTW, I don't want the file to be read-only). It is like file save dialog. I am using C# console .Net. I can save it to a specific location(with a path) now. Another problem, somehow, the excel file created by the program will be running forever in the background. Can anyone please help me? I have been working on this part for 2 days. Thank you so much.
Code:
private static void excelFile(System.Data.DataTable dtTable,List<Dictionary<string, object>> list)
{
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
string filepath = AppDomain.CurrentDomain.BaseDirectory;
Console.WriteLine(filepath);
string filename = #"output1.xlsx";
Console.WriteLine(filepath + filename);
// Microsoft.Office.Interop.Excel.Workbook wkbook = null;
var wkbook = xlApp.Workbooks.Add(Type.Missing);
wkbook.SaveAs(ReadOnlyRecommended: false);
_Worksheet wksheet = wkbook.ActiveSheet;
wksheet.Name = "APPLE";
try
{
for (var i = 0; i < dtTable.Columns.Count; i++)
{
wksheet.Cells[1, i + 1] = dtTable.Columns[i].ColumnName;
}
//rows
for (var i = 0; i < dtTable.Rows.Count; i++)
{
for (var j = 0; j < dtTable.Columns.Count; j++)
{
wksheet.Cells[i + 2, j + 1] = dtTable.Rows[i][j];
}
}
//System.IO.FileInfo fileInfo = new System.IO.FileInfo(filename);
//File.SetAttributes(filename, ~FileAttributes.ReadOnly);
//File.SetAttributes(filename, ~FileAttributes.Hidden);
//xlApp.ActiveWorkbook.Save();
// wkbook.Save();
//wkbook.Close();
//xlApp.ActiveWorkbook.Close();
xlApp.Workbooks.Close();
xlApp.Quit();
}
finally
{
if (wksheet != null) Marshal.ReleaseComObject(wksheet);
if (wkbook != null) Marshal.ReleaseComObject(wkbook);
if (xlApp != null) Marshal.ReleaseComObject(xlApp);
}
}
Finally I figured it out. The code below works.(ignore the catch block )
Code:
private static void excelFile(System.Data.DataTable dtTable, List<Dictionary<string, object>> list)
{
// File save dialog
SaveFileDialog saveFileDialog = new SaveFileDialog();
saveFileDialog.Filter = "Execl files (*.xls)|*.xls";
saveFileDialog.FilterIndex = 0;
saveFileDialog.RestoreDirectory = true;
saveFileDialog.CreatePrompt = true;
saveFileDialog.FileName = null;
saveFileDialog.Title = "Save path of the file to be exported";
//string filepath = AppDomain.CurrentDomain.BaseDirectory;
Excel.Application xlApp = null;
Excel.Workbooks wkbooks = null;
Excel.Workbook wkbook = null;
Excel.Sheets wksheets = null;
Excel.Worksheet wksheet = null;
try
{
xlApp = new Excel.Application();
wkbooks = xlApp.Workbooks;
wkbook = wkbooks.Add();
wksheets = wkbook.Sheets;
wksheet = wksheets.Add();
Console.WriteLine(list[0].Values);
wksheet.Name = "APPLE";
try
{
Console.WriteLine("It is working.");
for (var i = 0; i < dtTable.Columns.Count; i++)
{
wksheet.Cells[1, i + 1] = dtTable.Columns[i].ColumnName;
}
//rows
for (var i = 0; i < dtTable.Rows.Count; i++)
{
for (var j = 0; j < dtTable.Columns.Count; j++)
{
wksheet.Cells[i + 2, j + 1] = dtTable.Rows[i][j];
}
}
//wkbook.SaveAs(saveFileDialog, XlFileFormat.xlExcel8,false,
//false, false,false, XlSaveAsAccessMode.xlNoChange, Type.Missing,
//Type.Missing, Type.Missing,Type.Missing, Type.Missing);
Console.WriteLine("Processing!");
Console.WriteLine("File saved.");
wkbooks.Close();
wkbook.Close(false, Missing.Value, Missing.Value);
xlApp.Quit();
}
catch(Exception exp)
{
}
}
catch (Exception e)
{
//Console.WriteLine(e.ToString());
}
finally
{
if (wksheets != null) Marshal.ReleaseComObject(wksheets);
if (wkbook != null) Marshal.ReleaseComObject(wkbook);
if (wkbooks != null) Marshal.ReleaseComObject(wkbooks);
if (xlApp != null) Marshal.ReleaseComObject(xlApp);
}
}
}

Quickly read data from Excel

I have the code below reading data from an Excel worksheet and converting it to a pipe delimited text file. It works. The problem is it's quite slow as I have to read 1 cell at a time in order to add in the pipe.
I wondered if there was a better way to do this i.e. read the data into memory/array in one step and act on it there.
public string Process(string filename)
{
Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Range range;
string str = "";
int rCnt = 0;
int cCnt = 0;
object misValue = System.Reflection.Missing.Value;
xlApp = new Excel.Application();
xlWorkBook = xlApp.Workbooks.Open(filename, 0, true, 5, "", "", true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1); //Use the 1st worksheet
StreamWriter sw = new StreamWriter(destpath);
range = xlWorkSheet.UsedRange;
for (rCnt = 1; rCnt <= range.Rows.Count; rCnt++)
{
if ((rCnt % 1000) == 0)
{
txtProgress.Text = "Rows processed: "+ rCnt;
}
for (cCnt = 1; cCnt <= range.Columns.Count; cCnt++)
{
str = str + ToStr((range.Cells[rCnt, cCnt] as Excel.Range).Value2) + "|";
}
sw.WriteLine(str);
str = "";
}
xlWorkBook.Close(true, null, null);
xlApp.Quit();
sw.Close();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
MessageBox.Show("Complete","Status");
return "Success";
}
public static string ToStr(object readField)
{
if ((readField != null))
{
if (readField.GetType() != typeof(System.DBNull))
{
return Convert.ToString(readField);
}
else
{
return "";
}
}
else
{
return "";
}
}
private void releaseObject(object obj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
obj = null;
}
catch (Exception ex)
{
obj = null;
MessageBox.Show("Unable to release the Object " + ex.ToString());
}
finally
{
GC.Collect();
}
}
If you plan on only performing a read on the excel file content, I suggest you use the ExcelDataReader library Link, which extracts the worksheetData into a DataSet object.
static void Main(string[] args)
{
IExcelDataReader reader = null;
string FilePath = "PathToExcelFile";
//Load file into a stream
FileStream stream = File.Open(FilePath, FileMode.Open, FileAccess.Read);
//Must check file extension to adjust the reader to the excel file type
if (System.IO.Path.GetExtension(FilePath).Equals(".xls"))
{
reader = ExcelReaderFactory.CreateBinaryReader(stream);
}
else if (System.IO.Path.GetExtension(FilePath).Equals(".xlsx"))
{
reader = ExcelReaderFactory.CreateBinaryReader(stream);
}
if (reader != null)
{
//Fill DataSet
System.Data.DataSet result = reader.AsDataSet();
try
{
//Loop through rows for the desired worksheet
//In this case I use the table index "0" to pick the first worksheet in the workbook
foreach (DataRow row in result.Tables[0].Rows)
{
string FirstColumn = row[0].ToString();
}
}
catch
{
}
}
}
you can use LinqToExcel nuget package
https://www.nuget.org/packages/LinqToExcel/1.10.1
sample code:
string path = #"Users.xlsx";
var excel = new ExcelQueryFactory(path);
return (from c in excel.Worksheet<User>()
select c).OrderBy(a => a.Name).ToList();

How do I auto size columns through the Excel interop objects?

Below is the code I'm using to load the data into an Excel worksheet, but I'm look to auto size the column after the data is loaded. Does anyone know the best way to auto size the columns?
using Microsoft.Office.Interop;
public class ExportReport
{
public void Export()
{
Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Excel.Workbook wb;
Excel.Worksheet ws;
Excel.Range aRange;
object m = Type.Missing;
string[,] data;
string errorMessage = string.Empty;
try
{
if (excelApp == null)
throw new Exception("EXCEL could not be started.");
// Create the workbook and worksheet.
wb = excelApp.Workbooks.Add(Office.Excel.XlWBATemplate.xlWBATWorksheet);
ws = (Office.Excel.Worksheet)wb.Worksheets[1];
if (ws == null)
throw new Exception("Could not create worksheet.");
// Set the range to fill.
aRange = ws.get_Range("A1", "E100");
if (aRange == null)
throw new Exception("Could not get a range.");
// Load the column headers.
data = new string[100, 5];
data[0, 0] = "Column 1";
data[0, 1] = "Column 2";
data[0, 2] = "Column 3";
data[0, 3] = "Column 4";
data[0, 4] = "Column 5";
// Load the data.
for (int row = 1; row < 100; row++)
{
for (int col = 0; col < 5; col++)
{
data[row, col] = "STUFF";
}
}
// Save all data to the worksheet.
aRange.set_Value(m, data);
// Atuo size columns
// TODO: Add Code to auto size columns.
// Save the file.
wb.SaveAs("C:\Test.xls", Office.Excel.XlFileFormat.xlExcel8, m, m, m, m, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, m, m, m, m, m);
// Close the file.
wb.Close(false, false, m);
}
catch (Exception) { }
finally
{
// Close the connection.
cmd.Close();
// Close Excel.
excelApp.Quit();
}
}
}
Add this at your TODO point:
aRange.Columns.AutoFit();
This might be too late but if you add
worksheet.Columns.AutoFit();
or
worksheet.Rows.AutoFit();
it also works.
Also there is
aRange.EntireColumn.AutoFit();
See What is the difference between Range.Columns and Range.EntireColumn.
This method opens already created excel file, Autofit all columns of all sheets based on 3rd Row. As you can see Range is selected From "A3 to K3" in excel.
public static void AutoFitExcelSheets()
{
Microsoft.Office.Interop.Excel.Application _excel = null;
Microsoft.Office.Interop.Excel.Workbook excelWorkbook = null;
try
{
string ExcelPath = ApplicationData.PATH_EXCEL_FILE;
_excel = new Microsoft.Office.Interop.Excel.Application();
_excel.Visible = false;
object readOnly = false;
object isVisible = true;
object missing = System.Reflection.Missing.Value;
excelWorkbook = _excel.Workbooks.Open(ExcelPath,
0, false, 5, "", "", false, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows, "",
true, false, 0, true, false, false);
Microsoft.Office.Interop.Excel.Sheets excelSheets = excelWorkbook.Worksheets;
foreach (Microsoft.Office.Interop.Excel.Worksheet currentSheet in excelSheets)
{
string Name = currentSheet.Name;
Microsoft.Office.Interop.Excel.Worksheet excelWorksheet = (Microsoft.Office.Interop.Excel.Worksheet)excelSheets.get_Item(Name);
Microsoft.Office.Interop.Excel.Range excelCells =
(Microsoft.Office.Interop.Excel.Range)excelWorksheet.get_Range("A3", "K3");
excelCells.Columns.AutoFit();
}
}
catch (Exception ex)
{
ProjectLog.AddError("EXCEL ERROR: Can not AutoFit: " + ex.Message);
}
finally
{
excelWorkbook.Close(true, Type.Missing, Type.Missing);
GC.Collect();
GC.WaitForPendingFinalizers();
releaseObject(excelWorkbook);
releaseObject(_excel);
}
}
Have a look at this article, it's not an exact match to your problem, but suits it:
Craig Murphy - Excel – wordwrap row autosize issue

Categories

Resources