I'm creating my own search and replace function for excel with an extra ribbon. I want to find a certain string in an excel-document (not an existing document, visual studio opens excel automaticly when I run the application). The problem is that he can't find the value we give in an editbox (txtFind) in the spreadsheet. The application gives an error in my loop, when I create a cell-object.
This is the code:
Excel.Application exc = new Excel.Application();
if (exc == null)
{
Console.WriteLine("ERROR: EXCEL couldn't be started!");
}
Workbooks workbooks = exc.Workbooks;
Workbook workbook = workbooks.Add(XlWBATemplate.xlWBATWorksheet);
Sheets sheets = workbook.Worksheets;
Worksheet worksheet = (Worksheet)sheets.get_Item(1);
if (worksheet == null)
{
Console.WriteLine("ERROR: worksheet == null");
}
for (int i = 1; i < 150; i++)
{
for (int j = 1; j < 150; j++)
{
var cell = (worksheet.Cells[i, j] as Excel.Range).Value;
if (cell == txtFind.Text.ToString())
{
MessageBox.Show("FOUND");
}
else
{
cell.FindNext();
}
}
}
Excel.Application exc = new Excel.Application();
if (exc == null)
{
Console.WriteLine("ERROR: EXCEL couldn't be started!");
}
Workbooks workbooks = exc.Workbooks;
Workbook workbook = workbooks.Add(XlWBATemplate.xlWBATWorksheet);
Sheets sheets = workbook.Worksheets;
Worksheet worksheet = (Worksheet)sheets.get_Item(1);
if (worksheet == null)
{
Console.WriteLine("ERROR: worksheet == null");
}
Excel.Range range = worksheet.UsedRange;
Excel.Range currentFind;
currentFind = range.Cells.Find(txtFind.Text.ToString(), Type.Missing, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlWhole,
Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, false, false, false);
if (currentFind != null)
{
MessageBox.Show("found");
}
else
{
MessageBox.Show("not found");
}
This is my new piece of code ... still the currentFind has a null value. When I run the application through Visual Studio, I fill some cells with values I want to find, so I am not checking on an existing file.
You are only searching the first 150 rows and 150 columns. What if there is data in row 151?
Why are you doing a .FindNext? This is only to be called if you are doing a Find() operation. The Find() operation is a better choice for you then manually searching for all rows and columns.
Most likely the reason for your nullrefexception is that the range doesn't exist. If you insist on hard coding the ranges (150x150) then check that the value is not null with an IF statement. You're better off however using the sheet.UsedRange range which will tell you how much of the sheet you need to search through.
The code above will never find the row, as you are adding a new blank sheet and then searching it. A new blank sheet will never contain your value.
Related
I am writing a winform app that reads data from an sql database, paste it into excel and then saves the file in a given location.
My current issue is i'm encountering system error : 0x800AC472 when saving down the excel file.
So far I have tried adding
GC.Collect();
GC.WaitForPendingFinalizers();
to the on click method, after calling the excel save function.
From my googling it seems as though it may be due to the COM object not being removed after usage? these GC methods were meant to clear this, but it doesn't seem to be working properly. The reason I think it's not working properly is that there is still a microsoftoffice.exe process running in task manager after executing the code and receiving the error.
Something else worthy of mention is that if i wrap the code in a try-catch, the error is pasted to the console and the excel file is saved without issue, the only issue being that the process is still running in the task manager.
Is anyone here able to help me isolate the issue in my code causing this error? Thank you.
Here is the code that is called upon button press;
else if (((DataGridView)sender).Columns[e.ColumnIndex].DataPropertyName == "Run")
{
// return SQL into datatable
var returnedDT = SQLAcess.SQLtoDataTable(dataGridView1[0, e.RowIndex].Value.ToString()!);
//find item to open
string loadstring = DataGridClass.CellColumn(dataGridView1, "Load_Location", e.RowIndex);
//finds workbook to paste into.
var SettingsDataset = XMLData.ReturnXMLDataset(2);
var workbookstring = XMLData.returnXMLcellwithcolumnname(SettingsDataset, "Data_Dump_Worksheet_name", e.RowIndex);
//find location to save it
string savestring = DataGridClass.CellColumn(dataGridView1, "Save_location", e.RowIndex);
//execute export to excel, with the locations saved from above.
GXOMIClassLibrary.My_DataTable_Extensions.ExportToExcelDetailed(returnedDT, loadstring, workbookstring, savestring);
GC.Collect();
GC.WaitForPendingFinalizers();
}
The
GXOMIClassLibrary.My_DataTable_Extensions.ExportToExcelDetailed(returnedDT, loadstring, workbookstring, savestring);
method refers to a class library I have created with this method below;
public static void ExportToExcelDetailed(this System.Data.DataTable DataTable, string ExcelLoadPath, string WorksheetName, string ExcelSavePath)
{
try
{
int ColumnsCount;
//if datatable is empty throw an exception.
if (DataTable == null || (ColumnsCount = DataTable.Columns.Count) == 0)
throw new Exception("ExportToExcel: Null or empty input table!\n");
// load excel, and create a new workbook
//Microsoft.Office.Interop.Excel.Application Excel = new Microsoft.Office.Interop.Excel.Application();
//Excel.Workbooks.Add();
var excelApp = new Excel.Application();
Excel.Workbook excelWorkbook = excelApp.Workbooks.Open(ExcelLoadPath);
//TELL THE PROGRAM WHAT WORKBOOK TO OPEN
// select the right worksheet.
var Worksheet = excelWorkbook.Sheets[WorksheetName];
// DataCells
int RowsCount = DataTable.Rows.Count;
object[,] Cells = new object[RowsCount, ColumnsCount];
for (int j = 0; j < RowsCount; j++)
for (int i = 0; i < ColumnsCount; i++)
Cells[j, i] = DataTable.Rows[j][i];
//find last row
var xlRange = (Excel.Range)Worksheet.Cells[Worksheet.Rows.Count, 1];
long lastRow = (long)xlRange.get_End(Excel.XlDirection.xlUp).Row;
long newRow = lastRow + 1;
///cells[2,1] needs to become cell below last paste
Worksheet.Range((Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[newRow, 1]), (Microsoft.Office.Interop.Excel.Range)(Worksheet.Cells[newRow + RowsCount -1, ColumnsCount])).Value = Cells;
// check fielpath
if (ExcelSavePath != null && ExcelSavePath != "")
{
try
{
Worksheet.SaveAs(ExcelSavePath);
excelApp.Quit();
// Worksheet.Close(0);
//richTextBox1("Excel file saved!");
}
catch (Exception ex)
{
throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
+ ex.Message);
excelApp.Quit();
}
}
else // no filepath is given
{
excelApp.Visible = true;
}
excelApp.Quit();
}
catch (Exception ex)
{
throw new Exception("ExportToExcel: \n" + ex.Message);
}
}
changing this part of the ExportToExcelDetailed seems to have corrected the issue;
if (ExcelSavePath != null && ExcelSavePath != "")
{
try
{
Worksheet.SaveAs(ExcelSavePath);
excelApp.Quit();
Marshal.ReleaseComObject(Worksheet);
GC.Collect();
GC.WaitForPendingFinalizers();
}
catch (Exception ex)
{
throw new Exception("ExportToExcel: Excel file could not be saved! Check filepath.\n"
+ ex.Message);
excelApp.Quit();
}
}
else // no filepath is given
{
excelApp.Visible = true;
}
I need help writing a function that will input one string into a cell in Excel using C#.
This issue I am having is when I try to use a counter to make sure the sheet only created one time I get an error. If I don't have the if statement there, the code will just make numerous sheets and only save the last data point in the cell that equals the value of Excelcounter.
public void WriteSample()
{
Excel.Application excelApp = new Excel.Application();
if (excelApp != null)
{
if (Excelcounter == 0) // data_count keeps track of how many operations i have made to excel
{
Excel.Workbook excelWorkbook = excelApp.Workbooks.Add(); // Initalize the excell sheet
Excel.Worksheet excelWorksheet = (Excel.Worksheet)excelWorkbook.Sheets.Add();
}
Excelcounter++; // increment
// in the lines below anything that has to with the variable "excelWorkbook" and "excelWorksheet' will give an error
excelWorksheet.Cells[Excelcounter, 1] = str4; // add data to excel (this is where i am getting my error)
excelWorkbook.Close(); // close Excel
excelApp.Quit();
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelWorksheet);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelWorkbook);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelApp);
GC.Collect();
GC.WaitForPendingFinalizers();
}
}
I know that the reason I am getting an error is because the variables are separated from their interface (not sure if interface is the correct term for it). I am very new to C# this is only my 2nd project using this language. Is there a way I can continue using the logic I have in the code above without adding massive amounts of code (this might confuse me even more)? Thank you very much guys!!
Try the following:
Add a reference to Microsoft.Excel Object Library (ex: Microsoft.Excel 16.0 Object Library)
On menu, click Project
Select Add Reference
Select COM
Select Microsoft.Excel xx.x Object Library (ex: Microsoft.Excel 16.0 Object Library)
Add the following using statements:
using System.IO;
using System.Diagnostics;
using Excel = Microsoft.Office.Interop.Excel;
Option 1:
If you want to set a string value referencing the cell by row,column:
public void ExcelWriteValue(string filename, int rowNum, int colNum, string dataValue, string worksheetName = "")
{
//Write cell value using row number and column number
//*Note: Excel cells, can also be referenced by name, such as "B2"
//
// All indices in Excel (rowNumber, columnNumber, etc...) start with 1
// The format is: <rowNumber>, <columnNumber>
// The top left-most column, is: 1,1
bool specifiedWorksheetFound = false;
object oMissing = System.Reflection.Missing.Value;
Excel.Application excelApp = null;
Excel.Worksheet previousActiveSheet = null;
Excel.Range range = null;
Excel.Workbook workbook = null;
Excel.Worksheet worksheet = null;
//keep track of existing worksheet names
SortedDictionary<string, bool> worksheetDict = new SortedDictionary<string, bool>();
int worksheetCount = 0;
try
{
//create new instance
excelApp = new Excel.Application();
//suppress displaying alerts (such as prompting to overwrite existing file)
excelApp.DisplayAlerts = false;
//set Excel visability
excelApp.Visible = false;
//if writing/updating a large amount of data
//disable screen updating by setting value to false
//for better performance.
//re-enable when done writing/updating data, if desired
//excelApp.ScreenUpdating = false;
if (excelApp != null)
{
if (File.Exists(filename))
{
System.Diagnostics.Debug.WriteLine("'" + filename + "' exists. Existing file will be modified.");
//open existing Excel file
workbook = excelApp.Workbooks.Open(filename);
//get number of existing worksheets
worksheetCount = workbook.Sheets.Count;
if (worksheetCount >= 1)
{
foreach (Excel.Worksheet ws in workbook.Sheets)
{
//System.Diagnostics.Debug.WriteLine("worksheet name: '" + ws.Name + "'");
if (!String.IsNullOrEmpty(worksheetName) && ws.Name == worksheetName)
{
//set value to desired/specified worksheet
worksheet = ws;
//set value
specifiedWorksheetFound = true;
}
if (!worksheetDict.ContainsKey(ws.Name))
{
//add worksheet name to dictionary
//the bool value isn't used, so it's value isn't important
//it exists because a Dictionary requires both a key and a value
worksheetDict.Add(ws.Name, true);
}
}
if (!String.IsNullOrEmpty(worksheetName) && !specifiedWorksheetFound)
{
//specified worksheet not found
System.Windows.Forms.MessageBox.Show("Error: Worksheet '" + worksheetName + "' not found in filename '" + filename + "'.", "Error - Worksheet Not Found", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return;
}
else if (!String.IsNullOrEmpty(worksheetName) && specifiedWorksheetFound)
{
//set value
previousActiveSheet = excelApp.ActiveSheet;
//specified worksheet found
//activate desired worksheet
worksheet.Activate();
}
else
{
//set value
previousActiveSheet = excelApp.ActiveSheet;
//no worksheet name specified
//default to 1st worksheet
worksheet = workbook.Sheets[1];
//active worksheet
worksheet.Activate();
}
}
else
{
//no worksheets exist
//add a worksheet and set the value to the new worksheet
worksheet = workbook.Sheets.Add();
}
}
else
{
System.Diagnostics.Debug.WriteLine("'" + filename + "' doesn't exit. Creating new workbook.");
//create new workbook
workbook = excelApp.Workbooks.Add();
//get number of existing worksheets
worksheetCount = workbook.Sheets.Count;
//add a worksheet and set the value to the new worksheet
worksheet = workbook.Sheets.Add();
}
//set cell location that data needs to be written to
//range = worksheet.Cells[rowNum, colNum];
//set value of cell
//range.Value = dataValue;
//set value of cell
worksheet.Cells[rowNum, colNum] = dataValue;
System.Diagnostics.Debug.WriteLine("Info: Value for cell " + rowNum + "," + colNum + " in worksheet '" + worksheet.Name + "' set.");
if (previousActiveSheet != null)
{
//restore active sheet to one that was previously the active sheet
//so that when the user opens the workbook, it will open to the last sheet he/she opened
worksheet = previousActiveSheet;
worksheet.Activate();
}
//save Workbook - if file exists, overwrite it
workbook.SaveAs(filename, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, Excel.XlSaveAsAccessMode.xlNoChange, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
System.Diagnostics.Debug.WriteLine("Status: Complete. " + DateTime.Now.ToString("HH:mm:ss"));
}
}
catch (Exception ex)
{
string errMsg = "Error: ExcelWriteValue - " + ex.Message;
System.Diagnostics.Debug.WriteLine(errMsg);
if (ex.Message.StartsWith("Cannot access read-only document"))
{
System.Windows.Forms.MessageBox.Show(ex.Message + "Please close the workbook, before trying again.", "Error - Unable To Write To Workbook", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
}
finally
{
if (workbook != null)
{
//set value
range = null;
previousActiveSheet = null;
worksheet = null;
//close workbook
workbook.Close();
//release all resources
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(workbook);
}
if (excelApp != null)
{
//close Excel
excelApp.Quit();
//release all resources
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelApp);
}
}
}
*Note: The SortedDictionary isn't used. I added it in case you need to keep track of existing worksheet names.
Option 2:
If you want to set a string value referencing the cell by name (ex: "B2"):
public void ExcelWriteValue(string filename, string cellName, string dataValue, string worksheetName = "")
{
//Write cell value using the Excel cell name (ex: B2)
//*Note: Excel cells, can also be referenced by row,column such as "1,2"
//
// All indices in Excel (rowNumber, columnNumber, etc...) start with 1
// The format is: <rowNumber>, <columnNumber>
// The top left-most column, is: 1,1
bool specifiedWorksheetFound = false;
object oMissing = System.Reflection.Missing.Value;
Excel.Application excelApp = null;
Excel.Worksheet previousActiveSheet = null;
Excel.Range range = null;
Excel.Workbook workbook = null;
Excel.Worksheet worksheet = null;
//keep track of existing worksheet names
SortedDictionary<string, bool> worksheetDict = new SortedDictionary<string, bool>();
int worksheetCount = 0;
try
{
//create new instance
excelApp = new Excel.Application();
//suppress displaying alerts (such as prompting to overwrite existing file)
excelApp.DisplayAlerts = false;
//set Excel visability
excelApp.Visible = false;
//if writing/updating a large amount of data
//disable screen updating by setting value to false
//for better performance.
//re-enable when done writing/updating data, if desired
//excelApp.ScreenUpdating = false;
if (excelApp != null)
{
if (File.Exists(filename))
{
System.Diagnostics.Debug.WriteLine("'" + filename + "' exists. Existing file will be modified.");
//open existing Excel file
workbook = excelApp.Workbooks.Open(filename);
//get number of existing worksheets
worksheetCount = workbook.Sheets.Count;
if (worksheetCount >= 1)
{
foreach (Excel.Worksheet ws in workbook.Sheets)
{
//System.Diagnostics.Debug.WriteLine("worksheet name: '" + ws.Name + "'");
if (!String.IsNullOrEmpty(worksheetName) && ws.Name == worksheetName)
{
//set value to desired/specified worksheet
worksheet = ws;
//set value
specifiedWorksheetFound = true;
}
if (!worksheetDict.ContainsKey(ws.Name))
{
//add worksheet name to dictionary
//the bool value isn't used, so it's value isn't important
//it exists because a Dictionary requires both a key and a value
worksheetDict.Add(ws.Name, true);
}
}
if (!String.IsNullOrEmpty(worksheetName) && !specifiedWorksheetFound)
{
//specified worksheet not found
System.Windows.Forms.MessageBox.Show("Worksheet '" + worksheetName + "' not found in filename '" + filename + "'.", "Error - Worksheet Not Found", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
return;
}
else if (!String.IsNullOrEmpty(worksheetName) && specifiedWorksheetFound)
{
//set value
previousActiveSheet = excelApp.ActiveSheet;
//specified worksheet found
//activate desired worksheet
worksheet.Activate();
}
else
{
//set value
previousActiveSheet = excelApp.ActiveSheet;
//no worksheet name specified
//default to 1st worksheet
worksheet = workbook.Sheets[1];
//active worksheet
worksheet.Activate();
}
}
else
{
//no worksheets exist
//add a worksheet and set the value to the new worksheet
worksheet = workbook.Sheets.Add();
}
}
else
{
System.Diagnostics.Debug.WriteLine("'" + filename + "' doesn't exit. Creating new workbook.");
//create new workbook
workbook = excelApp.Workbooks.Add();
//get number of existing worksheets
worksheetCount = workbook.Sheets.Count;
//add a worksheet and set the value to the new worksheet
worksheet = workbook.Sheets.Add();
}
//set cell location that data needs to be written to
//range = worksheet.Range[cellName];
//set value of cell
//range.Value = dataValue;
//set value of cell
worksheet.Range[cellName].Value = dataValue;
System.Diagnostics.Debug.WriteLine("Info: Value for cell " + cellName + " in worksheet '" + worksheet.Name + "' set.");
if (previousActiveSheet != null)
{
//restore active sheet to one that was previously the active sheet
//so that when the user opens the workbook, it will open to the last sheet he/she opened
worksheet = previousActiveSheet;
worksheet.Activate();
}
//save Workbook - if file exists, overwrite it
workbook.SaveAs(filename, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, Excel.XlSaveAsAccessMode.xlNoChange, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value);
System.Diagnostics.Debug.WriteLine("Status: Complete. " + DateTime.Now.ToString("HH:mm:ss"));
}
}
catch (Exception ex)
{
string errMsg = "Error: ExcelWriteValue - " + ex.Message;
System.Diagnostics.Debug.WriteLine(errMsg);
if (ex.Message.StartsWith("Cannot access read-only document"))
{
System.Windows.Forms.MessageBox.Show(ex.Message + "Please close the workbook, before trying again.", "Error - Unable To Write To Workbook", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
}
}
finally
{
if (workbook != null)
{
//set value
range = null;
previousActiveSheet = null;
worksheet = null;
//close workbook
workbook.Close();
//release all resources
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(workbook);
}
if (excelApp != null)
{
//close Excel
excelApp.Quit();
//release all resources
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excelApp);
}
}
}
*Note: The SortedDictionary isn't used. I added it in case you need to keep track of existing worksheet names.
If this was helpful, please mark it as the answer.
I can use XlCellType.xlCellTypeLastCell to find last cell in the used range. How to get first cell in one line ?
Code to get last cell position.
Excel.Range mergeCells = (Excel.Range)mergeSheet.Cells[6,1].EntireRow;
var rowRng = mergeCells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing);
var colPosition = rowRng.Column;
One way is to get mergeCells.value and loop through to increment a counter until I see null/empty value. But I was hoping to get this in one line.
Any ideas ?
Test Cases:
(1)
Expected Result colPosition = 1
(2)
Expected Result colPosition = 5
Here is a solution using the Excel Interop library (as tagged in the question). The below method will return a 1-based column index of the first cell in a given row. It worked for me on your supplied test cases as well as a few of my own. Note that if you wish to simply use the first row in the used range - rather than a supplied row, you can find the first used row number using ActiveSheet.UsedRange.Rows[1].Row.
public static int FindFirstCellInExcelRow(string filePath, int rowNum)
{
Excel.Application xlApp = null;
Excel.Workbook wkBook = null;
Excel.Worksheet wkSheet = null;
Excel.Range range = null;
try
{
xlApp = new Excel.Application();
wkBook = xlApp.Workbooks.Open(filePath);
wkSheet = wkBook.ActiveSheet;
range = wkSheet.Cells[rowNum, 1].EntireRow;
if (range.Cells[1, 1].Value != null)
{
return range.Cells[1, 1].Column;
}
var result = range.Find(What: "*", After: range.Cells[1, 1], LookAt: Excel.XlLookAt.xlPart, LookIn: Excel.XlFindLookIn.xlValues, SearchOrder: Excel.XlSearchOrder.xlByColumns, SearchDirection: Excel.XlSearchDirection.xlNext, MatchByte: false, MatchCase: false);
int colIdx = result?.Column ?? 0; // return 0 if no cell in row contains value
return colIdx;
}
finally
{
wkBook.Close();
Marshal.ReleaseComObject(xlApp);
Marshal.ReleaseComObject(wkBook);
Marshal.ReleaseComObject(wkSheet);
Marshal.ReleaseComObject(range);
xlApp = null;
wkBook = null;
wkSheet = null;
range = null;
}
}
I highly (x10) recommend using ClosedXML over Microsoft's Excel libraries (unless you are using the old xls files). Using ClosedXML you would do the following (this is taken right from their webpage):
Get it right off the NuGet packages. Install-Package ClosedXML -Version 0.93.1
https://github.com/ClosedXML/ClosedXML/wiki/Finding-and-extracting-the-data
var wb = new XLWorkbook(northwinddataXlsx);
var ws = wb.Worksheet("Data");
// Look for the first row used
var firstRowUsed = ws.FirstRowUsed();
// Narrow down the row so that it only includes the used part
var categoryRow = firstRowUsed.RowUsed();
// Move to the next row (it now has the titles)
categoryRow = categoryRow.RowBelow();
// Get all categories
while (!categoryRow.Cell(coCategoryId).IsEmpty())
{
String categoryName = categoryRow.Cell(coCategoryName).GetString();
categories.Add(categoryName);
categoryRow = categoryRow.RowBelow();
}
try the below code snippet, this will give the first row of a excel used range
Excel.Workbook xlWB = Globals.ThisAddIn.Application.ActiveWorkbook;
Excel.Worksheet xlWS = xlWB.ActiveSheet;
int firstRow = xlWS.UsedRange.Row;
I’m working on a project and I’ve ran into an exception that I don’t know how to fix. I’ve searched everywhere and can’t find a solution that helps.
I’m trying to cut a range on a spreadsheet that has found a specific value in a cell in Column A and paste the entire row of that specific value into a new spreadsheet starting from A2 and until the value is no longer found in the original spreadsheet.
My code currently pastes one row in the new spreadsheet then gives me this exception “The information cannot be pasted because the Cut area and the paste area are not the same size and shape.” The exception is happening at this point in the code;
Excel.Range from = currentFind.EntireRow;
Excel.Range to = oSheet.get_Range("A2:A2500");
I think I need to use the active cell and active sheet properties.
Please help me!
public void btnLoad_Click(object sender, EventArgs e)
{
Excel.Application oXL;
Excel._Workbook oWB;
Excel._Worksheet oSheet;
if (dmCheck.IsChecked == true && fldCheck.IsChecked == true)
{
oXL = new Excel.Application();
oXL.Visible = true;
oWB = (Excel._Workbook)(oXL.Workbooks.Add());
oSheet = (Excel._Worksheet)oWB.ActiveSheet;
string dXLPath = #"N:/DAILY2.xlsx";
Excel.Workbook dWB = oXL.Workbooks.Open(dXLPath);
Excel.Worksheet dSheet = dWB.Worksheets.get_Item(1);
Excel.Range dRng = dSheet.get_Range("B1");
dRng.EntireColumn.Hidden = true;
Excel.Range currentFind = null;
Excel.Range firstFind = null;
Excel.Range taskHazpoi = dSheet.get_Range("A2", "A2500");
currentFind = taskHazpoi.Find("HAZPOI", Type.Missing, Excel.XlFindLookIn.xlValues, Excel.XlLookAt.xlPart, Excel.XlSearchOrder.xlByRows, Excel.XlSearchDirection.xlNext, false, Type.Missing, Type.Missing);
while(currentFind != null)
{
if (firstFind == null)
{
firstFind = currentFind;
}
else if (currentFind.get_Address(Excel.XlReferenceStyle.xlA1) == firstFind.get_Address(Excel.XlReferenceStyle.xlA1))
{
break;
}
Excel.Range from = currentFind.EntireRow;
Excel.Range to = oSheet.get_Range("A2:A2500");
from.Cut(to);
currentFind = taskHazpoi.FindNext(currentFind);
}
else if (dmCheck.IsChecked == false && fldCheck.IsChecked == false)
{
MessageBox.Show("Please check the DM and Flood box", "Report Loader");
}
I recommend you use Epplus instead of the interop Excel (i used it).
Advantages:
No requires office package installed in system.
No instance of Excel in memory.
Methods more clear.
Example of use:
http://zeeshanumardotnet.blogspot.com.es/2011/06/creating-reports-in-excel-2007-using.html?m=1
You found it in Nuget.
Regards,
You try to copy an entire row into the cell area A2:A2500, that's what triggers the exception.
For the 'to' range, take oSheet.get_Range("A2").EntireRow or oSheet.get_Range("A:A").
Hey folks I am trying to export a datatable to an excel spreadsheet (excel 15.0 library, excel 2013, VS 2013), and I am running into an issue. Right now I'm not worried so much about getting column headers and all that I'd just be happy with getting the data into the spreadsheet, my code is below and when I run it I keep getting
Object reference not set to an instance of an object
on the
workSheet.Cells[(i+2),(j+1)]
line of code.
public static void exportReport(System.Data.DataTable Results)
{
try
{
string excelFilePath = #"C:\exceltest\exceltestsheet.xlsx";
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel._Worksheet workSheet = excelApp.ActiveSheet;
if (Results == null || Results.Columns.Count == 0)
{
throw new Exception("null or empty table");
}
for (int i = 0; i < Results.Rows.Count; i++)
{
for (int j = 0; j < Results.Columns.Count; j++)
{
workSheet.Cells[(i + 2), (j + 1)] = Results.Rows[i][j];
}
}
if (excelFilePath != null && excelFilePath != "")
{
workSheet.SaveAs(excelFilePath);
excelApp.Quit();
Console.WriteLine("Excel File Saved!");
}
}
catch(Exception ex)
{
}
}
I believe you have to create a new workbook before accessing the active sheet. Try:
excelApp.Workbooks.Add();
BEFORE accessing the active worksheet.