I am trying to update a program that does work for office 2010 but gives an error for 2013.
The code I am running is this:
private static bool writeToExcel(DataTable dT)
{
// Create a new Excel document
Console.Write("Opening Excel...");
Excel.Application objExcel = new Excel.Application();
objExcel.Visible = false;
Excel.Workbooks objBooks = objExcel.Workbooks;
Excel.Workbook objBook = objBooks.Add();
Excel.Worksheet objSheet = (Excel.Worksheet)objExcel.Worksheets["Sheet1"]; objSheet.Name = "Data";
Excel.Worksheet newWorksheet;
newWorksheet = (Excel.Worksheet)objExcel.Worksheets.Add();
Excel.Worksheet objSheet2 = (Excel.Worksheet)objExcel.Worksheets["Sheet2"]; objSheet2.Name = "Data2";
Excel.Range objRange;
objSheet2.Cells[2, 1] = "###";
objSheet2.Cells[3, 1] = "###";
objSheet2.Cells[4, 1] = "$$$";
objSheet2.Cells[1, 2] = "%%%";
objSheet2.Cells[2, 2] = %%%Count;
objSheet2.Cells[3, 2] = %%%RespCount;
objSheet2.Cells[4, 2] = Math.Round(%%%RespCount / %%%Count, 1);
objSheet2.Cells[1, 3] = "^^^";
objSheet2.Cells[2, 3] = ^^^Count;
objSheet2.Cells[3, 3] = ^^^RespCount;
objSheet2.Cells[4, 3] = Math.Round(^^^Count / ^^^RespCount, 1);
objSheet2.Cells[1, 5] = "&&&";
objSheet2.Cells[2, 5] = &&&;
objSheet2.Cells[3, 5] = &&&Resp;
objSheet2.Cells[4, 5] = Math.Round(&&& / &&&Resp, 1);
objSheet2.Cells[1, 6] = "***";
objSheet2.Cells[2, 6] = ***;
objSheet2.Cells[3, 6] = ***Resp;
objSheet2.Cells[4, 6] = Math.Round(*** / ***Resp, 1);
// Add the column headers
int colCount = 1;
int rowCount = 1;
foreach (DataColumn column in dT.Columns)
{
Console.Write(".");
objSheet.Cells[rowCount, colCount] = DB.GetColumnName(column.ColumnName);
if (column.DataType == System.Type.GetType("System.String"))
{
objRange = objExcel.Range[objExcel.Cells[2, colCount], objExcel.Cells[dT.Rows.Count + 1, colCount]];
objRange.NumberFormat = "#";
}
if (column.DataType == System.Type.GetType("System.DateTime"))
{
objRange = objExcel.Range[objExcel.Cells[2, colCount], objExcel.Cells[dT.Rows.Count + 1, colCount]];
objRange.NumberFormat = "m/d/yy h:mm AM/PM";
}
colCount++;
}
// Format the column headers
Console.WriteLine();
Console.Write("Adding columns...");
try
{
objSheet.Range[objExcel.Cells[rowCount + 1, 1], objExcel.Cells[rowCount + 1, dT.Columns.Count]].Select();
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
The Error I get when I try it on a Win 7 PC running Office 2013 is this.
System.Runtime.InteropServices.COMException (0x800A03EC): Exception from HRESULT: 0x800A03EC
at System.Dynamic.ComRuntimeHelpers.CheckThrowException(Int32 hresult,
ExcepInfo& excepInfo, UInt32 argErr, String message)
at CallSite.Target(Closure , CallSite , Object , Object , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
at CscSurveyReporter.Program.writeToExcel(DataTable dT) in c:\tfs_csc\csc\CscSurveyReporter\CscSurveyReporter\Program.cs:line 236
The line I am having the exception on is:
objSheet.Range[objExcel.Cells[rowCount + 1, 1], objExcel.Cells[rowCount + 1, dT.Columns.Count]].Select();
I have looked online for a solution and I have tried to update the Microsoft.Office.Interop.Excel and I have also tried to remove a registry folder but nothing I have found and tried has worked.
I found two ways to solve the issue:
1)
int column = 0, row = 0;
foreach (DataColumn col in dT.Columns)
{
objExcel.Cells[1, ++column] = col.ColumnName;
}
foreach (DataRow r in dT.Rows)
{
row++;
column = 0;
foreach (DataColumn c in dT.Columns)
{
objExcel.Cells[row + 1, ++column] = r[c.ColumnName];
}
}
This worked but increased the run time of the application.
After I had that working I looked more at the line that was in error and changed it from:
objSheet.Range[objExcel.Cells[rowCount + 1, 1], objExcel.Cells[rowCount + 1, dT.Columns.Count]].Select();
too this:
objSheet.Range[objSheet.Cells[rowCount + 1, 1], objSheet.Cells[rowCount + 1, dT.Columns.Count]].Select();
I am posting this just incase anyone else has the same issue.
Related
Here is my code...
Microsoft.Office.Interop.Excel.Application Excel = new Microsoft.Office.Interop.Excel.Application();
Workbook wb = Excel.Workbooks.Add(XlSheetType.xlWorksheet);
Worksheet ws = (Worksheet)Excel.ActiveSheet;
Excel.Visible = true;
ws.Cells[1, 1] = "ID";
ws.Cells[1, 2] = "Name";
ws.Cells[1, 3] = "Detail";
ws.Cells[1, 4] = "Category";
ws.Cells[1, 5] = "Brand";
ws.Cells[1, 6] = "In Stock";
ws.Cells[1, 7] = "Price";
ws.Cells[1, 8] = "Total";
for (int i = 2; i <= dgDetail.Rows.Count; i++)
{
for (int j = 2; j <= 8; j++)
{
ws.Cells[i, j] = dgDetail.Rows[i - 2].Cells[j - 1].Value;
}
}
Excel has 1,1 based arrays, the first cell is 1,1, so you did it right when you put "ID" to this cell. Your gridview looks zero-based.
1) You start to export dgDetail from row 0, which I think is right, but you skip one last row - you can rewrite your code a little bit to see it:
for (int i = 0; i <= dgDetail.Rows.Count-2; i++) {
dgDetail.Rows[i]; //pseudocode
}
Maybe it's how you planned it, but you don't export row dgDetail.Row.Count - 1
2)
for (int j = 2; j <= 8; j++) {
ws.Cells[i, j] = dgDetail.Rows[i - 2].Cells[j - 1].Value;
}
Here you need to change the first value of j to 1, because you start from second column otherwise:
ws.Cells[i, 2] = dgDetail.Rows[i - 2].Cells[2 - 1].Value;
I guess you are just confused by excel 1,1 based arrays a little bit,
Also, if you have big exports, it's better to write the whole array in one operation:
Range range = worksheet.Range[worksheet.Cells[1, 1], worksheet.Cells[2, 2]];
range.Value = new object[2, 2] { { 1, 2 }, { 3, 4 } };
In a group project I have to write a table to an Excel sheet. This I have done but I need to highlight the table area where the data goes, as can be seen on these pictures:
https://gyazo.com/51c57897d9a1ce8df000d6ff0f18de20
https://gyazo.com/bcc879cd7d1c5f12ccb853490dca22f2
The first picture shows how it should look without data, and the second picture shows my current file with the data loaded.
Is it possible to highlight like it is seen in the first picture where the data is supposed to be?
I have not been able to find any sources dealing with this online.
Here is the code that creates the Excel sheet. Take note that I have not looked into formatting the code properly, but it should be readable:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ExcelLibrary.SpreadSheet;
using System.Data;
using System.IO;
using System.Windows;
using Excel = Microsoft.Office.Interop.Excel;
namespace ProjectXstaal
{
class Print
{
public void LoadToExcel(DataTable dt)
{
string filetest = "filetest.xlsx";
double allHours = 0;
double overtimeHours = 0;
if (File.Exists(filetest))
{
File.Delete(filetest);
}
Excel.Application oApp;
Excel.Worksheet oSheet;
Excel.Workbook oBook;
oApp = new Excel.Application();
oBook = oApp.Workbooks.Add();
Excel.Worksheet ws = (Excel.Worksheet)oApp.ActiveSheet;
// Calculates the total hours worked and total overtime hours. not important for the question
for (int i = 0; i < dt.Rows.Count; i++)
{
string overtimeTemp = dt.Rows[i][3].ToString();
string temp = dt.Rows[i][2].ToString();
double temp2 = Double.Parse(temp);
double temp3 = Double.Parse(overtimeTemp);
overtimeHours += temp3;
allHours += temp2 + temp3;
if (i >= 40)
{
break;
}
}
// some formatting of the page
ws.Cells[3, 1] = "Tidsperiode:";
ws.Cells[3, 5] = "NAVN";
ws.Cells[3, 6] = dt.Rows[1][7].ToString();
ws.Cells[1, 5] = DateTime.Now.Year.ToString();
ws.Cells[1, 3] = "ARBEJDSSEDDEL";
ws.Cells[40, 1] = "SAMMENLAGT FOR UGEN";
ws.Cells[40, 5] = allHours;
ws.Cells[41, 1] = "UGENS TIMER FORDELES PÅ";
ws.Cells[43, 5] = overtimeHours;
ws.Cells[42, 5] = allHours - overtimeHours;
ws.Cells[42, 4] = "NORMALTIMER";
ws.Cells[43, 4] = "OVERARBEJDE";
ws.Cells[6, 1] = dt.Columns[1].ToString();
ws.Cells[6, 2] = dt.Columns[5].ToString();
ws.Cells[6, 3] = dt.Columns[0].ToString();
ws.Cells[6, 4] = dt.Columns[4].ToString();
ws.Cells[6, 5] = dt.Columns[2].ToString();
ws.Cells[6, 6] = dt.Columns[3].ToString();
ws.Cells[6, 7] = dt.Columns[6].ToString();
//prints the datatable to the excel sheet and stops when it cant fit anymore information
for (int i = 0; i < dt.Rows.Count; i++)
{
ws.Cells[i + 7, 1] = dt.Rows[i][1].ToString();
ws.Cells[i + 7, 2] = dt.Rows[i][5].ToString();
ws.Cells[i + 7, 3] = dt.Rows[i][0].ToString();
ws.Cells[i + 7, 4] = dt.Rows[i][4].ToString();
ws.Cells[i + 7, 5] = dt.Rows[i][2].ToString();
ws.Cells[i + 7, 6] = dt.Rows[i][3].ToString();
ws.Cells[i + 7, 7] = dt.Rows[i][6].ToString();
ws.Cells[i + 7, 1].Bold = true;
if (i >= 32)
{
break;
}
}
// Sets column width of the data.
ws.Range["A6"].ColumnWidth = 11;
ws.Range["B6"].ColumnWidth = 10;
ws.Range["C6"].ColumnWidth = 6.7;
ws.Range["D6"].ColumnWidth = 11;
ws.Range["E6"].ColumnWidth = 11;
ws.Range["F6"].ColumnWidth = 15;
ws.Range["G6"].ColumnWidth = 15;
oBook.SaveAs(filetest);
oBook.Close();
oApp.Quit();
MessageBox.Show("Det virker måske");
}
}
}
If you now the range which should be bold, use:
Microsoft.Office.Interop.Excel.Range range = xlWorkSheet.get_Range("A1:A6","G1:G6");
range.Font.Bold = true;
In this example, the first 6 rows and the first 7 seven columns get bold, assuming the cell in the top-left corner is "A1".
I hope this helps!
I am generating an excel output from a text file. i am using C# to make my application. Basically, I am sorting the 4th column in ascending order. But what happens is my last column is not numbering from 1 to n number..See this please https://imageshack.com/i/exeLuFw3j What i should do for this..
My code snippet:
private void button1_Click(object sender, EventArgs e)
{
//opening a folder
if (ofd.ShowDialog() == DialogResult.OK)
{
//processing selected text file
int[] cols = new int[] { 15, 15, 25, 15, 15, 15 };
string[] strLines = System.IO.File.ReadAllLines(textBox1.Text);
StringBuilder sb = new StringBuilder();
string line = string.Empty;
string LastComment = string.Empty;
string CarouselName = enter.Text;
int iCarousel = 0;
char seperator = '\t';
SortedDictionary<string, ExcelData> lstExcel = new SortedDictionary<string, ExcelData>();
ExcelData fline = null;
for (int i = 0; i < strLines.Length; i++)
{
line = RemoveWhiteSpace(strLines[i]).Trim();
if (line.Length == 0)
continue;
string[] cells = line.Replace("\"", "").Split(seperator);
if (i > 0)
{
//if (cells[1] != LastComment)
{
if (!lstExcel.ContainsKey(cells[1].Replace(" ", "_")))
{
//replacing some white spaces to underscores
fline = new ExcelData();
lstExcel.Add(cells[1].Replace(" ", "_"), fline);
fline.Footprint = cells[2].Replace(" ", "_");
fline.Comment = cells[1].Replace(" ", "_");
iCarousel++;
if (iCarousel > 45)
iCarousel = 1; //once it reaches number 45 it will go back to number 1
LastComment = cells[1];
fline.Location = String.Format("{0}:{1}", CarouselName, iCarousel);
}
else
{
fline = lstExcel[cells[1].Replace(" ", "_")];
}
fline.SrNo++;
fline.Total++;
}
if (fline.Designator == null)
fline.Designator = new List<string>();
fline.Designator.Add(cells[0].Replace(" ", "_"));
}
//Generating string in string builder
for (int c = 0; c < cells.Length; c++)
sb.Append(cells[c].Replace(" ", "_").PadRight(cols[c]));
if (i == 0)
sb.Append("Location".PadRight(15));// Here i am adding last column Location
else
sb.Append(String.Format("{0}:{1}", CarouselName, iCarousel).PadRight(15));//i am starting the numbering of location here.. The Location will be like "name:1, name:2, name:3.. like this
sb.Append("\r\n");
}
ExportInExcel(lstExcel, #"D:\myExcel.xls");
System.Windows.Forms.Application.Exit();
}
}
private void ExportInExcel(SortedDictionary<string, ExcelData> lstData, string excelPath)
{
Microsoft.Office.Interop.Excel.Application xlApp;
Microsoft.Office.Interop.Excel.Workbook xlWorkBook;
Microsoft.Office.Interop.Excel.Worksheet xlWorkSheet;
object misValue = System.Reflection.Missing.Value;
xlApp = new Microsoft.Office.Interop.Excel.Application();
xlWorkBook = xlApp.Workbooks.Add(misValue);
xlWorkSheet = (Microsoft.Office.Interop.Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
xlWorkSheet.Cells[2, 1] = "Part List";
xlWorkSheet.get_Range("A2", "A2").Font.Size = 24; //How you can set the font size
xlWorkSheet.get_Range("A2", "A2").Font.Bold = true;
xlWorkSheet.Cells[3, 1] = "Project PN:";
xlWorkSheet.Cells[4, 1] = "Project Name:";
xlWorkSheet.Cells[5, 1] = "Variant: ";
xlWorkSheet.get_Range("A3", "A5").Font.Bold = true; //How you can set the font bold
xlWorkSheet.Cells[6, 1] = "Report Date: " + DateTime.Now.ToString("hh:mm:ss tt");
xlWorkSheet.Cells[7, 1] = "Footprint: " + DateTime.Now.ToString("MMM dd, yyyy");
int rowStartIndex = 8;
xlWorkSheet.Cells[rowStartIndex, 1] = "Sr No.";
xlWorkSheet.Cells[rowStartIndex, 2] = "Total";
xlWorkSheet.Cells[rowStartIndex, 3] = "Designator";
xlWorkSheet.Cells[rowStartIndex, 4] = "MAX PN";
xlWorkSheet.Cells[rowStartIndex, 5] = "Footprint";
xlWorkSheet.Cells[rowStartIndex, 6] = "Location";
xlWorkSheet.get_Range("A" + rowStartIndex.ToString(), "F" + rowStartIndex.ToString()).Font.Bold = true; //How you can set the font bold
//Format Columns
xlWorkSheet.get_Range("A1", "A1").EntireColumn.ColumnWidth = 3;
xlWorkSheet.get_Range("B1", "B1").EntireColumn.ColumnWidth = 3;
xlWorkSheet.get_Range("C1", "C1").EntireColumn.ColumnWidth = 25;
xlWorkSheet.get_Range("D1", "D1").EntireColumn.ColumnWidth = 10;
xlWorkSheet.get_Range("E1", "E1").EntireColumn.ColumnWidth = 23;
xlWorkSheet.get_Range("F1", "F1").EntireColumn.ColumnWidth = 10;
xlWorkSheet.get_Range("C1", "C1").EntireColumn.WrapText = true;
xlWorkSheet.get_Range("E1", "E1").EntireColumn.WrapText = true;
//End
//Header color
xlWorkSheet.get_Range("A" + rowStartIndex.ToString(), "F" + rowStartIndex.ToString()).Interior.Color = System.Drawing.ColorTranslator.ToOle(Color.FromArgb(79,129,189));
Color Odd = Color.FromArgb(219, 229, 241);
Color even = Color.FromArgb(184, 204, 228);
int i = rowStartIndex; ;
foreach (ExcelData xls in lstData.Values)
{
i++;
//i+2 : in Excel file row index is starting from 1. It's not a 0 index based collection
xlWorkSheet.Cells[i, 1] = (i - rowStartIndex).ToString();
xlWorkSheet.Cells[i, 2] = xls.Total.ToString();
xlWorkSheet.Cells[i, 3] = String.Join(",", xls.Designator.ToArray());
xlWorkSheet.Cells[i, 4] = xls.Comment;
xlWorkSheet.Cells[i, 5] = xls.Footprint;
xlWorkSheet.Cells[i, 6] = xls.Location;
Color c = (i % 2) > 0 ? Odd : even;
xlWorkSheet.get_Range("A" + i.ToString(), "F" + i.ToString()).Interior.Color = System.Drawing.ColorTranslator.ToOle(c);
}
//DrawBorder(xlWorkSheet, "A2", "F" + i.ToString());
xlWorkBook.SaveAs(excelPath, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
xlWorkBook.Close(true, misValue, misValue);
xlApp.Quit();
releaseObject(xlWorkSheet);
releaseObject(xlWorkBook);
releaseObject(xlApp);
}
Please help out guys!!!
Stacy for that you need to change only two lines
1st line
fline.Location = String.Format("{0}:{1}", CarouselName, iCarousel);
to
fline.Location = CarouselName;
we will not applying numbering here.
And the second change is in ExportInExcel() method. In the loop we are assigning location to the excel cell.
xlWorkSheet.Cells[i, 6] = xls.Location;
Now, we just need to append the serial number after xls.Location property.
xlWorkSheet.Cells[i, 6] = xls.Location + (i - rowStartIndex).ToString();
We are deducting rowStartIndex from the i because the row can be started from any number. Now, It is starting from 8 and we don't need to start the location number from 8.
I am working on some code that a developer I replaced wrote. He wrote a lengthy piece of code what writes to multiple excel worksheets on the same excel file. I am thinking about using several background workers to speed up the process of writing to four excel worksheets. Would there be a reason why it would be a good idea to leave all this on one thread? I have used multi-threading before, but not in c# and not writing to excel. I could not find any documentation either way.
Here is the code
xlWorkSheet = xlWorkBook.Worksheets.get_Item(1);
// work order
xlWorkSheet.Cells[4, 4] = nld.s_WorkOrderNumber;
// technician
xlWorkSheet.Cells[6, 4] = nld.s_TechnicianName;
// date and time
xlWorkSheet.Cells[4, 10] = (string)DateTime.Now.ToShortDateString();
xlWorkSheet.Cells[6, 10] = (string)DateTime.Now.ToShortTimeString();
row = 30;
col = 1;
// left connectors and part number
conCount = nld.n_LeftConnCount;
for (i = 0; i < conCount; i++)
{
xlWorkSheet.Cells[row, col] = "Name: " + nld.ConnDataLeft[i].s_ConnName + " PartNo: " + nld.ConnDataLeft[i].s_ConnPartNumber;
row++;
}
// Right connectors and part number
row = 30;
col = 7;
conCount = nld.n_RightConnCount;
for (i = 0; i < conCount; i++)
{
xlWorkSheet.Cells[row, col] = "Name: " + nld.ConnDataRight[i].s_ConnName + " PartNo: " + nld.ConnDataRight[i].s_ConnPartNumber;
row++;
}
// put down the pin map onNetlist worksheet
xlWorkSheet = xlWorkBook.Worksheets.get_Item(2);
row = 5;
col = 1;
i = 0;
leftPinNum = 0;
int connCount = nld.pinMap.Count;
for(i = 0; i < connCount; i++)
{
xlWorkSheet.Cells[row, col] = (i+1).ToString();
leftPinNum = nld.pinMap[i].pinLeft;
xlWorkSheet.Cells[row, col + 1] = nld.pinMap[i].conLeftName;
xlWorkSheet.Cells[row, col + 2] = nld.pinMap[i].pinLeftName;
xlWorkSheet.Cells[row, col + 4] = nld.pinMap[i].conRightName;
xlWorkSheet.Cells[row, col + 5] = nld.pinMap[i].pinRightName;
row++;
}
// put down the pin map onNetlist worksheet
xlWorkSheet = xlWorkBook.Worksheets.get_Item(3);
row = 5;
col = 1;
i = 0;
leftPinNum = 0;
for (i = 0; i < connCount; i++)
{
xlWorkSheet.Cells[row, col] = (i + 1).ToString();
leftPinNum = nld.pinMap[i].pinLeft;
xlWorkSheet.Cells[row, col + 1] = nld.pinMap[i].conLeftName;
xlWorkSheet.Cells[row, col + 2] = nld.pinMap[i].pinLeftName;
xlWorkSheet.Cells[row, col + 4] = nld.pinMap[i].conRightName;
xlWorkSheet.Cells[row, col + 5] = nld.pinMap[i].pinRightName;
if (facadeIntoNetList.ReturnIfUseShort(i))
{
xlWorkSheet.Cells[row, col + 7] = "True";
}
else
{
xlWorkSheet.Cells[row, col + 9] = "True";
}
row++;
}
// put down the pin map onNetlist worksheet
xlWorkSheet = xlWorkBook.Worksheets.get_Item(4);
row = 5;
col = 1;
i = 0;
leftPinNum = 0;
for (i = 0; i < connCount; i++)
{
xlWorkSheet.Cells[row, col] = (i + 1).ToString();
leftPinNum = nld.pinMap[i].pinLeft;
xlWorkSheet.Cells[row, col + 1] = nld.pinMap[i].conLeftName;
xlWorkSheet.Cells[row, col + 2] = nld.pinMap[i].pinLeftName;
xlWorkSheet.Cells[row, col + 6] = nld.pinMap[i].conRightName;
xlWorkSheet.Cells[row, col + 7] = nld.pinMap[i].pinRightName;
row++;
}
I know the temptation to do this: Those Office COM interfaces are painfully slow. But they also don't support multithreading at all. It's not a C# issue, it is an Excel+COM issue. If you need speed, then write an .xlsx using a 3rd-party library then launch Excel to open the file. That might literally be hundreds of times faster.
I'm building a report in which try to copy the previous row cell styles in the following
for (int i = 0; i < DataSource.Length; i++)
{
int rowNumber = i + s;
Excel.Range RngToCopy = ObjWorkSheet.get_Range("A" + rowNumber.ToString(), "K" + rowNumber.ToString());
Excel.Range r = ObjWorkSheet.get_Range("A" + (rowNumber + 1).ToString(), "K" + (rowNumber + 1).ToString());
RngToCopy.Copy(Type.Missing);
r.Insert(Excel.XlInsertShiftDirection.xlShiftDown);
r.PasteSpecial(Excel.XlPasteType.xlPasteFormats,
Excel.XlPasteSpecialOperation.xlPasteSpecialOperationNone, false, false);
ObjWorkSheet.Cells[rowNumber, 1] = i + 1;
ObjWorkSheet.Cells[rowNumber, 2] = DataSource[i].TerminalName;
ObjWorkSheet.Cells[rowNumber, 3] = DataSource[i].Type;
ObjWorkSheet.Cells[rowNumber, 4] = DataSource[i].Requisite;
}
everything works but very long
How can I speed this up?
I think you manually copy you will be improved.
Object[] origData = origRange.Value2;
destRange.Value2 = origData;
That should be WAY faster.