I'm using this code to generate an Excel file. It should be simple to change the export to CSV file, just by modifying a parameter in the saveAs call, but it doesn't work. Any ideea why ?
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
xlApp.Visible = false;
if (xlApp == null)
{
MessageBox.Show("EXCEL could not be started. Check that your office installation and project references are correct.");
return false;
}
Workbook wb = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
try
{
if (details != false)
{
//Workbook wb = xlApp.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
wb.Worksheets.Add();
Worksheet detailsWs = (Worksheet)wb.Worksheets[2];
for (int i = 0; i < dt.Columns.Count; i++)
{
detailsWs.Cells[1, i + 1] = dt.Columns[i].Caption;
}
}
Worksheet ws = (Worksheet)wb.Worksheets[1];
if (ws == null)
{
MessageBox.Show("Worksheet could not be created. Check that your office installation and project references are correct.");
}
for (int i = 0; i < dt.Columns.Count; i++)
{
ws.Cells[1, i + 1] = dt.Columns[i].Caption;
}
for (int i = 0; i < dt.Rows.Count; i++)
{
for (int j = 0; j < dt.Columns.Count; j++)
{
ws.Cells[i + 2, j + 1] = dt.Rows[i].ItemArray[j];
}
worker.ReportProgress((i * 100) / dt.Rows.Count);
}
wb.SaveAs(filename, XlFileFormat.xlCSV, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlShared, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
wb.Close(true, filename);
return true;
}
catch (Exception ex)
{
throw ex;
}
finally
{
// Cleanup
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
if (wb != null)
{
wb.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(wb);
}
if (xlApp != null)
{
xlApp.Quit();
Marshal.FinalReleaseComObject(xlApp);
}
}
i used the old way. lines of strings, with commas
XlSaveAsAccessMode.xlShared is the reason. i don't know why but i get that error too.
I try changing XlSaveAsAccessMode.xlNoChange and XlSaveAsAccessMode.xlExclusive,
it worked!
Related
I have created the function shown below. Everything is working fine, the challenge now, is that I have some scenarios where it would be ideal to have the constructor 'RadGridView grid' as a Datatable. I'm looking for a constructor that can take the input type of 'RadGridView' or type of 'Datatable' - a kind of "universal" constructor, if that is possiple?
public static void Export(RadGridView grid, string sheetName)
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Excel file |*.xlsx";
saveFileDialog1.Title = "Save";
saveFileDialog1.ShowDialog();
if (saveFileDialog1.FileName != "")
{
Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
Microsoft.Office.Interop.Excel._Worksheet worksheet = null;
app.Visible = false;
worksheet = workbook.Sheets["Sheet1"];
worksheet = workbook.ActiveSheet;
worksheet.Name = sheetName;
Microsoft.Office.Interop.Excel.Range aRange = worksheet.UsedRange;
workbook.Worksheets[1].Cells.NumberFormat = "#";
for (int i = 1; i < grid.Columns.Count + 1; i++)
{
worksheet.Cells[1, i] = grid.Columns[i - 1].HeaderText;
}
for (int i = 0; i < grid.Rows.Count; i++)
{
for (int j = 0; j < grid.Columns.Count; j++)
{
worksheet.Cells[i + 2, j + 1] = grid.Rows[i].Cells[j].Value.ToString();
}
}
aRange.Value = aRange.Value;
aRange.Cells.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignLeft;
worksheet.Columns.AutoFit();
workbook.SaveAs(saveFileDialog1.FileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
app.Quit();
}
}
Thanks in advance!
I solved this by using the 'dynamic' keyword.
I'm generating an excel file in C# and excel file is format is as follows.
And Columns From C1 will be dynamic since there can be several dates.
And what I need to do is only allow editing for rows with Ctype
YYY
Is there any way to identify rows with Ctype = YYY
The code I use to generate excel is as follows
public string ExcelGenerator()
{
DataTable dt = GetDataTable();
var fileName = "ExcelFile";
var excelApp = new Application();
var workbooks = excelApp.Workbooks;
var excelWorkBook = workbooks.Add(XlWBATemplate.xlWBATWorksheet);
var sheets = excelWorkBook.Sheets;
var excelWorkSheet = sheets[1];
excelWorkSheet.Name = "ExcelFile";
int iCol = 1;
// Add column headings...
foreach (DataColumn c in dt.Columns)
{
excelWorkSheet.Cells[1, iCol] = c.ColumnName; ;
((Range)excelWorkSheet.Cells[1, iCol]).Interior.Color = ColorTranslator.ToOle(Color.DarkGray);
iCol++;
}
// for each row of data...
for (int j = 0; j < dt.Rows.Count; j++)
{
for (int k = 0; k < dt.Columns.Count; k++)
{
excelWorkSheet.Cells[j + 2, k + 1] = dt.Rows[j].ItemArray[k].ToString();
}
}
string fullpath = Path.Combine(excelPath, fileName);
if (File.Exists(fullpath))
{
try
{
File.Delete(fullpath);
}
catch (IOException e)
{
Console.Write(e.Message);
}
}
excelApp.DisplayAlerts = false;
excelWorkBook.SaveAs(fullpath, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault, Type.Missing, Type.Missing, true, false, XlSaveAsAccessMode.xlNoChange, XlSaveConflictResolution.xlLocalSessionChanges, Type.Missing, Type.Missing);
excelWorkBook.Close(false, Type.Missing, Type.Missing);
excelApp.Quit();
Marshal.ReleaseComObject(workbooks);
Marshal.ReleaseComObject(excelWorkSheet);
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(excelWorkBook);
Marshal.ReleaseComObject(excelApp);
excelWorkSheet = null;
excelWorkBook = null;
excelApp = null;
workbooks = null;
GC.WaitForPendingFinalizers();
GC.Collect();
return fileName;
}
Excel.Office.Interop don't allow range unprotection by programmatically.
For more information, you may visit this website.
https://msdn.microsoft.com/en-us/library/dkcs53f3.aspx
But if you use EPPlus library, you can do like Excel users.
if you allow selective editable column, excel requires sheet protection = true and some unprotected range.
(using EPPlus)
excelWorkSheet.Protection.IsProtected = true;
excelWorkSheet.ProtectedRanges.Add("editable", new ExcelAddress("B"));
I'm using Excel Interop for C# to export a datagridview to Excel and print it. I'm using this code:
try
{
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
excel.Application.Workbooks.Add(true);
int ColumnIndex = 0;
int rowIndex = -1;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
rowIndex++;
ColumnIndex = 0;
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
ColumnIndex++;
excel.Cells[rowIndex + 1, ColumnIndex] = row.Cells[col.Name].Value;
}
}
excel.Visible = true;
excel.DisplayAlerts = false;
Worksheet worksheet = (Worksheet)excel.ActiveSheet;
worksheet.Activate();
worksheet.Cells.Style.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter;
worksheet.Range[worksheet.Cells[1, 1], worksheet.Cells[1, 7]].Merge();
worksheet.Range[worksheet.Cells[2, 1], worksheet.Cells[2, 7]].Merge();
worksheet.Range[worksheet.Cells[3, 1], worksheet.Cells[3, 7]].Merge();
worksheet.Range[worksheet.Cells[4, 1], worksheet.Cells[4, 4]].Merge();
worksheet.Cells[1, 1].Font.Bold = true;
worksheet.Range["A1"].Cells.Font.Size = 15;
worksheet.Range["A4"].Cells.Font.Size = 15;
worksheet.Range["B7"].Cells.Font.Size = 15;
worksheet.Range["B8"].Cells.Font.Size = 15;
worksheet.Range["B9"].Cells.Font.Size = 15;
worksheet.Range["A11"].Cells.Font.Size = 15;
worksheet.Range["B13"].Cells.Font.Size = 15;
worksheet.PrintOut(Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
GC.Collect();
GC.WaitForPendingFinalizers();
excel.Quit();
}
catch (Exception ex)
{
MessageBox.Show("Error de exportación.");
}
It works fine, but I need to open an existing file to do this same thing to avoid reconfiguration of the printing margins. I checked other similar questions and tried to apply the "workBook = oXL.Workbooks.Open("path", ...);" but it can make it work. Any thoughts?
To open a file use the open method.
Microsoft.Office.Interop.Excel.Workbooks wkbks = null;
Microsoft.Office.Interop.Excel.Workbook wkbk = null;
wkbks = excel.Workbooks;
wkbk = wkbks.Open(xlsFileName);
At the end of your method you should do a cleanup on all your interop variables:
if (wkbk != null)
{
try
{
wkbk.Close(false);
}
catch
{
}
Marshal.FinalReleaseComObject(wkbk);
wkbk = null;
}
I am trying to export 2 datagridviews to excel but it is missing the last line of data for both of the sets of data grid views, I have checked the code and I cant see what I have done wrong? Also it is creating a temporary file when exporting and then locking the file and not exiting gracefully and only a reboot allows you to delete the file? Any help would be great code is below. For example if i save as test.xlsx I get 2 files ~$test.xlsx and test.xlsx and both both files are locked.
private void exprtbtn_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Excel._Application app = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Workbook workbook = app.Workbooks.Add(Type.Missing);
try
{
// creating new Excelsheet in workbook
Microsoft.Office.Interop.Excel._Worksheet worksheet1 = null;
Microsoft.Office.Interop.Excel._Worksheet worksheet2 = null;
// get the reference of first sheet. By default its name is Sheet1.
// store its reference to worksheet
worksheet1 = workbook.Sheets["Sheet1"];
worksheet1 = workbook.ActiveSheet;
// changing the name of active sheet
worksheet1.Name = "Switch Totals";
// storing header part in Excel
for (int i = 1; i < switchtotalgrd.Columns.Count + 1; i++)
{
worksheet1.Cells[1, i] = switchtotalgrd.Columns[i - 1].HeaderText;
}
// storing Each row and column value to excel sheet
for (int i = 0; i < switchtotalgrd.Rows.Count - 1; i++)
{
for (int j = 0; j < switchtotalgrd.Columns.Count; j++)
{
worksheet1.Cells[i + 2, j + 1] = switchtotalgrd.Rows[i].Cells[j].Value.ToString();
}
}
// Adding second worksheet
int count = workbook.Worksheets.Count;
Excel.Worksheet addedSheet = workbook.Worksheets.Add(Type.Missing,
workbook.Worksheets[count], Type.Missing, Type.Missing);
// get the reference of first sheet. By default its name is Sheet1.
// store its reference to worksheet
worksheet2 = workbook.Sheets["Sheet2"];
worksheet2 = workbook.ActiveSheet;
// changing the name of active sheet
worksheet2.Name = "Itemised Extn";
// storing header part in Excel
for (int i = 1; i < fullresult.Columns.Count + 1; i++)
{
worksheet2.Cells[1, i] = fullresult.Columns[i - 1].HeaderText;
}
// storing Each row and column value to excel sheet
for (int i = 0; i < fullresult.Rows.Count - 1; i++)
{
for (int j = 0; j < fullresult.Columns.Count; j++)
{
if (fullresult.Rows[i].Cells[j].Value == null)
{
fullresult.Rows[i].Cells[j].Value = "NA";
}
worksheet2.Cells[i + 2, j + 1] = fullresult.Rows[i].Cells[j].Value.ToString();
}
}
// save the application
string fileName = String.Empty;
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Excel files |*.xls|All files (*.*)|*.*";
saveFileDialog1.FilterIndex = 2;
saveFileDialog1.RestoreDirectory = true;
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
fileName = saveFileDialog1.FileName;
workbook.SaveAs(fileName, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
}
else
return;
}
//Catch all errors.
catch (System.Exception)
{
}
finally
{
workbook = null;
app = null;
}
}
You probably might want to double-check your outer for loop again, e.g. for (int i = 0; i < fullresult.Rows.Count - 1; i++), shouldn't it be using less than and equal perhaps?
Since you are using Excel com interop, you will need to call this method to be able to release the resource after you are done with it, Marshal.ReleaseComObject.
A good practice is to use try{...}catch{...}finally{...}, and release com object in the finally block.
I am not able to read data in Excel. Here is the code I am using:
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application xlApp = new Excel.Application();
Excel.Workbook xlWorkbook = xlApp.Workbooks.Open(#"Book1.xlsx", 0, true, 5, "", "", true, Excel.XlPlatform.xlWindows, "\t", false, false, 0, true, 1, 0);
Excel._Worksheet xlWorksheet = (Excel._Worksheet)xlWorkbook.Sheets[1];
Excel.Range xlRange = xlWorksheet.UsedRange;
int rowCount = xlRange.Rows.Count;
int colCount = xlRange.Columns.Count;
for (int i = 1; i <= rowCount; i++)
{
for (int j = 1; j <= colCount; j++)
{
MessageBox.Show(xlWorksheet.Cells[i,j].ToString());
}
}
I get a message box that says something about System.__ComObject instead of a value.
How can I fix this?
I found the solution for above, here is the code:
string temp = (string)(xlRange.Cells[i, j] as Excel.Range).Value2;
MessageBox.Show(temp);
Haven´t tested it, but I think it should read
MessageBox.Show(xlRange.Cells[i,j].ToString());
or alternatively
MessageBox.Show(xlRange.Cells[i,j].Value.ToString());
Try this:
MessageBox.Show(xlRange.Cells[i][j].Value);
use the following function to get data as DATATABLE object for N'th sheet :
public DataTable GetWorkSheet(int workSheetID)
{
string pathOfExcelFile = fileFullName;
DataTable dt = new DataTable();
try
{
excel.Application excelApp = new excel.Application();
excelApp.DisplayAlerts = false; //Don't want Excel to display error messageboxes
excel.Workbook workbook = excelApp.Workbooks.Open(pathOfExcelFile, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); //This opens the file
excel.Worksheet sheet = (excel.Worksheet)workbook.Sheets.get_Item(workSheetID); //Get the first sheet in the file
int lastRow = sheet.Cells.SpecialCells(excel.XlCellType.xlCellTypeLastCell, Type.Missing).Row;
int lastColumn = sheet.Cells.SpecialCells(excel.XlCellType.xlCellTypeLastCell, Type.Missing).Column;
excel.Range oRange = sheet.get_Range(sheet.Cells[1, 1], sheet.Cells[lastRow, lastColumn]);//("A1",lastColumnIndex + lastRow.ToString());
oRange.EntireColumn.AutoFit();
for (int i = 0; i < oRange.Columns.Count; i++)
{
dt.Columns.Add("a" + i.ToString());
}
object[,] cellValues = (object[,])oRange.Value2;
object[] values = new object[lastColumn];
for (int i = 1; i <= lastRow; i++)
{
for (int j = 0; j < dt.Columns.Count; j++)
{
values[j] = cellValues[i, j + 1];
}
dt.Rows.Add(values);
}
workbook.Close(false, Type.Missing, Type.Missing);
excelApp.Quit();
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message, "Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
return dt;
}
Try this code:
MessageBox.Show(((Excel.Range)xlRange.Cells[i,j]).Value2.ToString());
This code works sucessfully for me.