Excel range of non-consecutive rows to clipboard - c#

I have a FindRange that finds rows with the text `€´(lblValutaTeken.Text) in my Excel sheet.
What I need to do is get the rows(multiple!) that contain the text and copy them to clipboard. My range is not consecutive rows, which is the basis of my despair.
So far I got this
object[,] cellValues = null;
try
{
Excel.Range currentFind = null;
Excel.Range firstFind = null;
var missing = Missing.Value;
Excel.Range RangeWithValutaSigns = xlApp.ActiveSheet.Range("g1", "g500");
currentFind = RangeWithValutaSigns.Find(lblValutaTeken.Text, missing,
Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart,
Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, false,
missing, missing);
while (currentFind != null)
{
if (firstFind == null)
{
firstFind = currentFind;
}
else if (currentFind.get_Address(Excel.XlReferenceStyle.xlA1)
== firstFind.get_Address(Excel.XlReferenceStyle.xlA1))
{
break;
}
Console.WriteLine("~~~~ currentFind.Row = " + currentFind.Row);
Excel.Range currentFindRow = currentFind.Range[("B" + currentFind.Row), ("H" + currentFind.Row)];
cellValues = (object[,])currentFindRow.Value2;
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(cellValues))
{
string name = descriptor.Name;
object value = descriptor.GetValue(cellValues);
Console.WriteLine("{0}={1}", name, value);
}
for (int j = 1; j < 8; j++)
{
Console.WriteLine(cellValues[i, j].ToString());
}
i = i + 1;
currentFind = RangeWithValutaSigns.FindNext(currentFind);
}
}
catch (Exception ex)
{
MessageBox.Show("Er is een fout gemaakt tijdens het kopiëren van de productregels uit de offerte naar het clipboard." + System.Environment.NewLine + System.Environment.NewLine + "Controleer of er een excel geopend is met daarin regels met productcodes uit de LookApp." + System.Environment.NewLine + System.Environment.NewLine + "Error message:" + System.Environment.NewLine + ex.Message);
}
Clipboard.SetDataObject(cellValues);

I don't know if this will help you or not, but here is my idea:
If you are searching for rows with some text criteria, why not create a string array with that criteria, and then filter your excel file based on your criteria, afterwards, copying those rows.
Example :
string[] Criteria = new string[1]
Criteria[0] = "Your Criteria"; (if the criteria can vary you can use * )
Criteria[1] = "Some other Criteria";
And then filter your excel sheet based on a criteria:
Create a range:
Xl.Range myRange = yourSheet.UsedRange;
next filter :
myRange.AutoFilter(7, Criteria[0], xl.XlAutoFilterOperator.xlOr, Criteria[1], true);
xl.Range my_Range= myRange.SpecialCells(xl.XlCellType.xlCellTypeVisible, Type.Missing);
And now all you need to do is select and copy your remaining visible rows and paste them.
Hopefully this will be of some help.

So, with putting answers from multiple other Q&A's together I came up with this. Not very elegant, but it does precisely what I wanted it to.
Step 1. Create a datatable
Step 2. Use Excel.Range.Find to find the ranges(=cells) that have my valutasign (is same as lblvalutasign.txt, for instance € or $ or CAD)
Step 3. Each time a range is found I use Range.Offset to put cellvalues into my datable in the corresponding column.
Step 4. Put the whole datatable into a datagridview. This can be a non-visible datagridview if you want. Lay-out the datagridview the way you want to.
Step 5. DataGridView.SelectAll() and copy to clipboard with
DataObject d = dataGridView1.GetClipboardContent();
Clipboard.SetDataObject(d);
Step 6. Use ctr+v to paste anywhere!
Excel.Application xlApp = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
Excel.Range myRange;
myRange = xlApp.ActiveSheet.UsedRange;
DataTable dtProductRowsFromExcel = new DataTable(); //to save all productrows form excel offer.
dtProductRowsFromExcel.Columns.Add("Code", typeof(String)); //column 1 Excel B
dtProductRowsFromExcel.Columns.Add("Amount", typeof(String)); //column 2 Excel C
dtProductRowsFromExcel.Columns.Add("Unit", typeof(String)); //column 3 Excel D
dtProductRowsFromExcel.Columns.Add("ValutaUnit", typeof(String)); //column 4 Excel E
dtProductRowsFromExcel.Columns.Add("PriceUnit", typeof(String)); //column 5 Excel F
dtProductRowsFromExcel.Columns.Add("ValutaTotal", typeof(String)); //column 6 Excel G
dtProductRowsFromExcel.Columns.Add("PriceTotal", typeof(String)); //column 7 Excel H
try
{
Excel.Range currentFind = null;
Excel.Range firstFind = null;
var missing = Missing.Value;
Excel.Range RangeWithValutaSigns = xlApp.ActiveSheet.Range("g1", "g500");
currentFind = RangeWithValutaSigns.Find(lblValutaTeken.Text, missing,
Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart,
Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, false,
missing, missing);
while (currentFind != null)
{
if (firstFind == null)
{
firstFind = currentFind;
}
else if (currentFind.get_Address(Excel.XlReferenceStyle.xlA1)
== firstFind.get_Address(Excel.XlReferenceStyle.xlA1))
{
break;
}
Console.WriteLine("~~~~ currentFind.Row = " + currentFind.Row);
string B = currentFind.Offset[0, -5].Value2.ToString();
string C = (currentFind.Offset[0, -4].Value2 != null) ? currentFind.Offset[0, -4].Value2.ToString() : "";
string D = (currentFind.Offset[0, -3].Value2 != null) ? currentFind.Offset[0, -3].Value2.ToString() : "";
string E = (currentFind.Offset[0, -2].Value2 != null) ? currentFind.Offset[0, -2].Value2.ToString() : "";
string F = (currentFind.Offset[0, -1].Value2 != null) ? currentFind.Offset[0, -1].Value2.ToString() : "";
string G = currentFind.Value2.ToString();
string H = (currentFind.Offset[0, 1].Value2 != null) ? currentFind.Offset[0, 1].Value2.ToString() : "";
dtProductRowsFromExcel.Rows.Add(B, C, D, E, F, G, H);
currentFind = RangeWithValutaSigns.FindNext(currentFind);
}
// to check datatable in output window use:
foreach (DataRow dataRow in dtProductRowsFromExcel.Rows)
{
foreach (var item in dataRow.ItemArray)
{
Console.WriteLine(item);
}
}
dataGridView1.ReadOnly = true;
dataGridView1.RowHeadersVisible = false;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
dataGridView1.DataSource = dtProductRowsFromExcel;
dataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText;
dataGridView1.SelectAll();
DataObject d = dataGridView1.GetClipboardContent();
Clipboard.SetDataObject(d);
}
catch (Exception ex)
{
MessageBox.Show("Error message:" + System.Environment.NewLine + ex.Message);
}

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);

How to add pivot table filters with Microsoft.Office.Interop.Excel in C#

I create a pivot table based on an Excel (.xlsx) file. The program adds fields to rows, values, and the filter. Using PivotFilters.Add2 causes 0x800a03ec error which terminates the program. How to properly use PivotFilters.Add2?
I tried filtering on different fields with different data types. Also, I tried using Type.Missing in a place of unused arguments. There seems to be plenty of information of this method for VB, but not so much for C#.
Items selected in the filter should be between the two dates on the last line.
var xlApp = new Microsoft.Office.Interop.Excel.Application();
xlApp.Visible = true;
var workBook = xlApp.Workbooks.Open(spreadsheetLocation);
var workSheet1 = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Sheets["Data"];
var workSheet2 = (Microsoft.Office.Interop.Excel.Worksheet)workBook.Sheets.Add();
Microsoft.Office.Interop.Excel.Range last = workSheet1.Cells.SpecialCells(Microsoft.Office.Interop.Excel.XlCellType.xlCellTypeLastCell, Type.Missing);
Microsoft.Office.Interop.Excel.Range range = workSheet1.get_Range("A1", last);
Microsoft.Office.Interop.Excel.PivotCaches pivotCaches = null;
Microsoft.Office.Interop.Excel.PivotCache pivotCache = null;
Microsoft.Office.Interop.Excel.PivotTable pivotTable = null;
Microsoft.Office.Interop.Excel.PivotFields pivotFields = null;
Microsoft.Office.Interop.Excel.PivotField filterField = null;
Microsoft.Office.Interop.Excel.PivotField accNumField = null;
Microsoft.Office.Interop.Excel.PivotField amountPaidField = null;
pivotCaches = workBook.PivotCaches();
pivotCache = pivotCaches.Create(XlPivotTableSourceType.xlDatabase, range);
pivotTable = pivotCache.CreatePivotTable(workSheet2.Cells[1,1]);
pivotFields = (Microsoft.Office.Interop.Excel.PivotFields)pivotTable.PivotFields();
amountPaidField = (Microsoft.Office.Interop.Excel.PivotField)pivotFields.Item("AmountPaid");
amountPaidField.Orientation = Microsoft.Office.Interop.Excel.XlPivotFieldOrientation.xlDataField;
amountPaidField.NumberFormat = "$#,###,###.00";
accNumField = (Microsoft.Office.Interop.Excel.PivotField)pivotFields.Item("AccNumber");
accNumField.Orientation = Microsoft.Office.Interop.Excel.XlPivotFieldOrientation.xlRowField;
filterField = (Microsoft.Office.Interop.Excel.PivotField)pivotFields.Item("AccDate");
filterField.Orientation = Microsoft.Office.Interop.Excel.XlPivotFieldOrientation.xlPageField;
filterField.EnableMultiplePageItems = true;
filterField.PivotFilters.Add2(XlPivotFilterType.xlDateBetween, Type.Missing, DateTime.Now.AddDays(-30), DateTime.Now.AddDays(-20));
#First it deletes two rows and then it creates a pivot table#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Office.Interop.Excel;
namespace ConsoleApplication4
{
class Program
{
public static string Column(int column)
{
column--;
if (column >= 0 && column < 26)
return ((char)('A' + column)).ToString();
else if (column > 25)
return Column(column / 26) + Column(column % 26 + 1);
else
throw new Exception("Invalid Column #" + (column + 1).ToString());
}
static void Main(string[] args)
{
try
{
string path = #"C:\Users\UX155512\Documents\Book1fd.xlsx";
var excelFile = new Application();
Workbook workBook = excelFile.Workbooks.Open(path);
Worksheet workSheet = workBook.Worksheets[1];
Worksheet pivotSheet = workBook.Worksheets.Add(
System.Reflection.Missing.Value,
workBook.Worksheets[workBook.Worksheets.Count],
1,
System.Reflection.Missing.Value);
Range last = workSheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing);
int lastRow = last.Row;
int lastCol = last.Column;
string lastColVal = Column(lastCol);
string lastFilledCol = lastColVal + lastRow.ToString();
Console.WriteLine(lastFilledCol);
Console.WriteLine(lastColVal);
Console.WriteLine(lastRow);
Console.WriteLine(lastCol);
for (int i = 1; i <= lastRow; i++)
{
if (workSheet.Cells[1][i].Value == ("HDR"))
{
workSheet.Rows[i].Delete();
Console.WriteLine("The Row Containing HDR has been deleted");
}
if (workSheet.Cells[1][i].Value == ("TRL"))
{
workSheet.Rows[i].Delete();
Console.WriteLine("The Row Containing TLR has been deleted");
}
}
Range lastRange = workSheet.Range["A1", lastFilledCol];
pivotSheet.Name = "Pivot Table";
Range range = pivotSheet.Cells[1, 1];
PivotCache pivotCache = (PivotCache)workBook.PivotCaches().Add(XlPivotTableSourceType.xlDatabase, lastRange);
PivotTable pivotTable = (PivotTable)pivotSheet.PivotTables().Add(PivotCache: pivotCache, TableDestination: range);
PivotField pivotField = (PivotField)pivotTable.PivotFields("Plan Number");
pivotField.Orientation = XlPivotFieldOrientation.xlRowField;
PivotField pivotField2 = (PivotField)pivotTable.PivotFields("Source");
pivotField2.Orientation = XlPivotFieldOrientation.xlColumnField;
PivotField pivotField3 = (PivotField)pivotTable.PivotFields("Total");
pivotField3.Orientation = XlPivotFieldOrientation.xlDataField;
pivotField3.Function = XlConsolidationFunction.xlSum;
workBook.SaveAs(#"C:\Users\UX155512\Documents\Excel Dump\Trial9.xlsx");
workBook.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.Read();
}
}
}
As mentioned above by Asger, the filter can't be added to a page field. Instead, the pivot item's visibility property has to be set.
var pivotItems = filterField.PivotItems();
DateTime date = Convert.ToDateTime(item.Name);
foreach (var item in pivotItems)
{
item.Visible = false;
if (date < DateTime.Now.AddDays(-30) || date > DateTime.Now.AddDays(-20))
{
item.Visible = true;
}
}
The best way to find the answer to pretty much ANY interop question is to record a macro then examine the source.

C# Appending list to excel file

so currently my code below generates a string and adds it to a list for each image file in a directory, then after its does adding to the list, it opens an excel file, appends the list, and formats it. Currently my problem is that my excel line is selecting the entireColumn and pasting the list, how can I get it to recognize how many strings are in the list and only append that many to the excel sheet.
//Fill A2:B6 with an array of values .
oRng = oSheet.get_Range("C2");
oRng.EntireColumn.Value2 = checkInformation.ToArray();
Here is my whole project
class Program
{
[STAThread]
static void Main(string[] args)
{
Microsoft.Office.Interop.Excel.Application oXL;
Microsoft.Office.Interop.Excel._Workbook oWB;
Microsoft.Office.Interop.Excel._Worksheet oSheet;
Microsoft.Office.Interop.Excel.Range oRng;
object misvalue = System.Reflection.Missing.Value;
Console.WriteLine("Initializing Check Parser Menu.....");
string dataPath = #"C:\Users\User\Desktop\Tesseract\Tesseract\tessdata";
string[] filePaths = Directory.GetFiles(#"C:\Users\User\Desktop\Tesseract\Tesseract\Check_Images", "*.png");
string checkData = "";
int checkCounter = 0;
List<string> checkInformation = new List<string>();
foreach (string filePath in filePaths)
{
checkCounter++;
Console.WriteLine("Initializing Check Parser... on Check: " + checkCounter);
using (TesseractEngine ocr = new TesseractEngine(dataPath, "eng", EngineMode.TesseractOnly))
{
using (Pix p = Pix.LoadFromFile(filePath))
{
using (Pix img = p.Scale(2, 3))
{
using (var page = ocr.Process(img))
{
string text = page.GetText();
if (text.Contains("Claim ID"))
{
int indexOfNone = text.IndexOf("NONE");
int indexOfClaimId = text.IndexOf("Claim ID");
int difference = indexOfClaimId - indexOfNone;
var dollarData = text.Substring(indexOfNone, difference);
int startingPoint = indexOfNone + (dollarData.Length - 6);
var dollarAmount = text.Substring(startingPoint, 6);
var claimIdData = text.Substring(indexOfClaimId, 14);
var claimInfoOutput = claimIdData + " Check Amount: " + dollarAmount;
Console.WriteLine(claimInfoOutput);
checkInformation.Add(claimInfoOutput);
}
else
{
Console.WriteLine("You will need to locate this check, there was an issue parsing " + "\n" + filePath);
Console.WriteLine("Press any Key to continue");
Console.ReadKey();
}
}
}
}
}
}
Console.WriteLine("Writing Data to Excel File... DONT TaCH");
try
{
//Start Excel and get Application object.
oXL = new Microsoft.Office.Interop.Excel.Application();
oXL.Visible = true;
//Get a new workbook.
oWB = (Microsoft.Office.Interop.Excel._Workbook)(oXL.Workbooks.Add(""));
oSheet = (Microsoft.Office.Interop.Excel._Worksheet)oWB.ActiveSheet;
//Add table headers going cell by cell. //Format A1:B1 as bold, vertical alignment = center.
oSheet.Cells[1, 1] = "Claim ID";
oSheet.Cells[1, 2] = "Check Amount";
oSheet.get_Range("A1", "B1").Font.Bold = true;
oSheet.get_Range("A1", "B1").VerticalAlignment = Microsoft.Office.Interop.Excel.XlVAlign.xlVAlignCenter;
// Create an array to multiple values at once.
//Fill A2:B6 with an array of values .
oRng = oSheet.get_Range("C2");
oRng.Value2 = checkInformation.ToArray();
//oSheet.get_Range("A2", "B6").Value2 = checkInformation.ToArray();
//Fill A2 with a formula(=MID(C2,9,5)
oRng = oSheet.get_Range("A2", "A50");
oRng.Formula = "=MID(C2,9,5)";
//Fill B2 with a =RIGHT(C2,6)
oRng = oSheet.get_Range("B2", "B50");
oRng.Formula = "=RIGHT(C2,6)";
//AutoFit columns A:C.
oRng = oSheet.get_Range("A1", "C1");
oRng.EntireColumn.AutoFit();
oXL.Visible = false;
oXL.UserControl = false;
oWB.SaveAs("C:\\Users\\User\\Desktop\\Tesseract\\Tesseract\\excel\\checkdata.xlsx", Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookDefault,
Type.Missing, Type.Missing,
false, false, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
oWB.Close();
;
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
Okay I solved it guys sorry to bug you but heres what I did.
//Fill A2:B6 with an array of values .
string cellName;
int counter = 2;
foreach (var check in checkInformation)
{
cellName = "C" + counter.ToString();
oRng = oSheet.get_Range(cellName, cellName);
oRng.Value2 = check.ToString();
++counter;
}
and basically i just need to say for each item in my list this is the first cell name append the value.tostring

From DataBase to Excel : date format issue

I'm currently trying to export some data from my database to an Excel file. Everything goes fine except for one column.
I've got two date fields in my targeted table (start and end date) which I want to display in my Excel sheet. The thing is, the end date is correctly displayed (dd/mm/yyyy) while my start date isn't (mm/dd/yyyy). Their definition are absolutely the same at the database level.
Here's how I'm building my DataTable :
public System.Data.DataTable ExportLastChangesToExcel()
{
List<HD_DISCOUNTS> listDiscount = (from d in dbHosp.HD_DISCOUNTS where d.TO_EXTRACT == "N" orderby d.EXTRACT_TEXT descending select d).ToList();
System.Data.DataTable table = new System.Data.DataTable();
table.Columns.Add("Condition Type", typeof(string));
table.Columns.Add("Sales organisation", typeof(string));
table.Columns.Add("Distribution Channel", typeof(string));
table.Columns.Add("Customer", typeof(string));
table.Columns.Add("Customer Name", typeof(string));
table.Columns.Add("Material", typeof(string));
table.Columns.Add("Material name", typeof(string));
table.Columns.Add("Amount", typeof(string));
table.Columns.Add("Unit", typeof(string));
table.Columns.Add("C..", typeof(string));
table.Columns.Add("Valid From", typeof(string));
table.Columns.Add("Valid To", typeof(string));
table.Columns.Add("Valid Action", typeof(string));
var allCust = (from v in dbCust.CUSTOMER_MASTER where v.INCLUDE_INTO_HD == "Y" select v).ToList();
foreach (HD_DISCOUNTS disc in listDiscount)
{
string compareId = disc.ID_HOSP.ToString();
CUSTOMER_MASTER cust = (from h in allCust where h.SOLDTOPARTY.TrimStart('0') == compareId select h).FirstOrDefault();
DIM_PRODUCT prod = (from p in db.DIM_PRODUCT where p.P_KEY_AZ == disc.ID_PRODUCT select p).FirstOrDefault();
DIM_PRODUCT_SAP sap = (from s in db.DIM_PRODUCT_SAP where s.P_KEY_AZ == prod.P_KEY_AZ && s.P_TYPE_SAP == "Domestic" select s).FirstOrDefault();
table.Rows.Add("ZD22", "BE10", "1", cust.SOLDTOPARTY, cust.SOLDTOPARTY_DESC, sap.P_KEY_SAP.ToString(), prod.P_DESC_AZ, disc.DISCOUNT.ToString(), "%", "A", disc.START_DATE.Value.ToString("dd/MM/yyyy"), disc.END_DATE.Value.ToString("dd/MM/yyyy"), disc.EXTRACT_TEXT);
}
return table;
}
I have debugged and start date should be well displayed. Here's the code I use to build my Excel :
protected void btnExport_Click(object sender, EventArgs e)
{
Microsoft.Office.Interop.Excel.Application excel;
Microsoft.Office.Interop.Excel.Workbook worKbooK;
Microsoft.Office.Interop.Excel.Worksheet worksheet;
Microsoft.Office.Interop.Excel.Range celLrangE;
try
{
excel = new Microsoft.Office.Interop.Excel.Application();
excel.Visible = false;
excel.DisplayAlerts = false;
worKbooK = excel.Workbooks.Add(Type.Missing);
worksheet = (Microsoft.Office.Interop.Excel.Worksheet)worKbooK.ActiveSheet;
worksheet.Name = "Sheet1";
System.Data.DataTable tab = ExportLastChangesToExcel();
Range excelRange = worksheet.get_Range("K1");
excelRange.NumberFormat = "dd/mm/yyyy;#";
int rowcount = 2;
foreach (DataRow datarow in tab.Rows)
{
rowcount += 1;
for (int i = 1; i <= tab.Columns.Count; i++)
{
if (rowcount == 3)
{
worksheet.Cells[1, i] = tab.Columns[i - 1].ColumnName;
worksheet.Cells.Font.Color = System.Drawing.Color.Black;
}
worksheet.Cells[rowcount-1, i] = datarow[i - 1].ToString();
//worksheet.Cells[i, 11].NumberFormat = "#";
if (rowcount > 3)
{
if (i == tab.Columns.Count)
{
if (rowcount % 2 == 0)
{
celLrangE = worksheet.Range[worksheet.Cells[rowcount, 1], worksheet.Cells[rowcount, tab.Columns.Count]];
}
}
}
}
}
celLrangE = worksheet.Range[worksheet.Cells[1, 1], worksheet.Cells[rowcount, tab.Columns.Count]];
celLrangE.EntireColumn.AutoFit();
celLrangE = worksheet.Range[worksheet.Cells[1, 1], worksheet.Cells[2, tab.Columns.Count]];
worKbooK.SaveAs("C:\\Temp\\Hospital Discount\\Genpact\\GenpactExtract.xlsx");
worKbooK.Close();
excel.Quit();
}
catch (Exception ex)
{
}
finally
{
worksheet = null;
celLrangE = null;
worKbooK = null;
lblResultMessage.Text = "Extract for Genpact has been successfully generated";
lblResultMessage.Visible = true;
}
As the column K is the one containing the wrong dates, I tried to format this column to get my dates well formatted, but without success.
Any idea on what's possibly going wrong ?
I think the issue is you are leaving too much to Excel and need to be explicit in how you enter and render the data.
My recommendation:
Read the data from the database as a date, not a string
Enter it into Excel as a date, as Excel interprets dates
Format the cell the way you want to see it
Example:
Excel.Range r = worksheet.Cells[rowcount - 1, i];
if (datarow[i - 1] is DateTime)
{
r.Value2 = ((DateTime)(datarow[i - 1])).ToOADate();
r.NumberFormat = "dd/MM/yyyy";
}
else
{
r.Value2 = datarow[i - 1]
}
Bear in mind you can skip the datatable all together and just use an OracleDataReader to read the data and then put it directly into Excel.
Further, if you have an ODBC connection, you can have Excel read it directly from Oracle and put it into a Table -- it will even handle the dates properly if you do it that way. You can still do this from C#, by the way, with a few lines of code, and you let Excel do the heavy lifting.

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