I've got an Excel workbook, and needed to read data from the third (and final) worksheet in that workbook. I used old code that scanned through all worksheets, but modified it to jump to the third worksheet:
foreach (var worksheet in Workbook.Worksheets(excelInput).skip(2))
This took me to the third worksheet, my code would execute, and everything was fine.
Now, the client is sending either a three-tabbed Workbook with the sheet I need elsewhere (either 1st or 2nd tab), or they're sending a four-tabbed Workbook, and the sheet I need could be anywhere.
Is there a way to choose the one-and-only sheet that I need by either finding the name of the tab, or the text in cell A1, and using that worksheet and that worksheet only?
Thanks very much in advance!
If you do not know “where” the worksheet is located in the workbook, you can loop through each sheet and check either the sheet name, or as you say “text in cellA1”.
Checking the text in cell A1… I am not sure how you would know if the sheet was the proper one by looking at the first cell. What if all sheets have a value in the first cell? And what would that cell contain? Would the cell contain text that says “this is the correct sheet”? So I am assuming that this workbook only has one sheet with data, and the other sheets are empty.
Looping through the sheets in the workbook is relatively easy, however if you do not know what the name of the sheet is, then it may be difficult to identify the proper sheet. Using my assumption (above) of only one sheet with data, then you can check each sheet to see how many rows of data each sheet has. Then the one with more than 1 row of data is the sheet you are looking for. If the other sheets have data also, then this won’t work and you are going to have to identify the target sheet some other way.
If you DO KNOW the name of the worksheet, then you are good to go. In your case you stated that the worksheet was “Sheet3” but may not be in the 3rd index of the worksheets in the workbook. In this case you can reference the sheet by name as you asked with:
Worksheet target = workbook.Sheets[“Sheet3”];
If target returns null, then the worksheet named “Sheet3” does not exist. If target is not null, then you have found the worksheet and it can be referenced by the target Worksheet variable.
From what you described, if the sheet is always named ”Sheet3” then simply use:
if (SheetExist(workbook, "Sheet3"))
{
Worksheet myWS = workbook.Sheets["Sheet3"];
if (myWS.Cells[1,1].Value != null)
Console.WriteLine("\nCell[1,1] of sheet3: " + myWS.Cells[1, 1].Value.ToString() + "\n");
else
Console.WriteLine("\nCell[1,1] of sheet3 is Null/has no value");
}
else
{
//Console.WriteLine("Worksheet NOT found!");
// sheet named "Sheet3" does not exist in the workbook
}
Below is a method that you can use to see if a "worksheet" with the supplied name “sheetName” exist in the given ”workbook.” If you need the index of the worksheet you could change this to return the index or -1 if it does not exist.
private static bool SheetExist(Excel.Workbook workbook, string sheetName)
{
Worksheet target = workbook.Sheets[sheetName];
if (target != null)
{
//Console.WriteLine("Worksheet found!");
return true;
}
else
{
//Console.WriteLine("Worksheet NOT found!");
return false;
}
A method that loops through all the sheets and checks the number of rows with data using the “UsedRange” function. This also identifies the index of the worksheet in the workbook.
private static void LoopThruAllSheets(Workbook workbook)
{
Sheets allWorkSheets = workbook.Worksheets;
foreach (Worksheet curWS in allWorkSheets)
{
Console.WriteLine("Worksheet : at index " + curWS.Index + " name: " + curWS.Name.ToString() + " UsedRange.Rows.Count: " + curWS.UsedRange.Rows.Count.ToString());
}
}
Hope this helps
Related
I would like to add a column that already contains cells values between two columns (or at the end) of a worksheet of an existing workbook that I load.
So I have a function that sets that "column values" I need :
private static Workbook SetIndicatorsWorkbook()
{
var workbook = new Workbook(WorkbookFormat.Excel2007MacroEnabled);
var worksheet = workbook.Worksheets.Add("Unit & Integration Tests");
//Don't worry about team and jenkinsBuilTeams variables
foreach (var team in jenkinsBuildTeams)
{
worksheet.Rows[posX].Cells[0].Value = lastnbUnitTests + lastnbIntegrationTests;
posX += 1;
}
return workbook;
}
And then in main function I want to add this column (which is workbook.worksheets[0].Columns[0] ) in a loaded workbook :
private static void Main()
{
//The workbook I need to update
Workbook workbook = Workbook.Load("file.xlsx");
Workbook temp = SetIndicatorsWorkbook();
WorksheetColumn wc = temp.Worksheets[0].Columns[0];
//The issue is that Worksheet's Columns collection has no "Insert" property
workbook.Save("file.xlsx");
}
The Columns collection of the Worksheet has an Insert method that will shift data/formatting just as would happen in Excel. This was added in the 2014 volume 2 version. You can read more about that in the help topic or the api documentation. Note I've linked to the WPF version help but the Insert method is available in the other platforms as well.
I have the following error...
System.Data.DuplicateNameException: 'A column named 'samplex' already
belongs to this DataTable.'
I have large multiple excel files that need merging into one. But all the column names are the same. So I think that is why I am getting this error.
All the data is in sheet1 one from each excel files. Searching on the net the best one I found was using Spire.Xls, sample taken from here
My code sample, using console...
using Spire.Xls;
::
::
Workbook workbook = new Workbook();
workbook.LoadFromFile(#"filea.xlsx");
Workbook workbook2 = new Workbook();
workbook2.LoadFromFile(#"fileb.xlsx");
Workbook workbook3 = new Workbook();
workbook3.LoadFromFile(#"filec.xlsx");
Worksheet sheet2 = workbook3.Worksheets[0];
DataTable dataTable = sheet2.ExportDataTable();
Worksheet sheet1 = workbook.Worksheets[0];
sheet1.InsertDataTable(dataTable, false, sheet1.LastRow + 1, 1);
//save the workbook
workbook.SaveToFile("result.xlsx");
Appreciate if anyone can help me on this?
Since you're able to get DataTable objects and all the column names are the same, I'd bet you could use DataTable.Merge() -
Workbook workbook1 = ...;
Workbook workbook2 = ...;
DataTable bookTable1 = workbook1.ExportDataTable();
DataTable booktable2 = workbook2.ExportDataTable();
bookTable1.Merge(bookTable2);
// Spire specific API calls to save bookTable1 to Excel file
The only requirement for your data is that you have a key column. To configure the DataTable with a key -
bookTable1.PrimaryKey = bookTable1.Columns("DataID" /* your key column name here */);
When I used Microsoft.Office.Interop.Excel, sample taken from here, it solve the problem regarding columns with same name. The code is long and complicated but it works but you will need Microsoft Office on the machine. Only a slight problem is that the results shows in new sheet, it doesn't go directly into sheet1. If anyone can advise me on this, it will be ideal.
I am using Visual Studio 2017.
You can use CellRange.Copy(CellRange destRange) method in Spire.XLS to merge worksheets from different workbooks into one, it won't throw the DuplicateNameException.
Refer to the following code:
//Load the first workbook
Workbook workbook1 = new Workbook();
workbook1.LoadFromFile("Sample.xlsx");
Worksheet sheet1 = workbook1.Worksheets[0];
//Load the second workbook
Workbook workbook2 = new Workbook();
workbook2.LoadFromFile("sample2.xlsx");
Worksheet sheet2 = workbook2.Worksheets[0];
int a = sheet2.LastRow;
int b = sheet2.LastColumn;
//Copy data from the 2nd row in sheet2 into sheet1
sheet2.Range[2, 1, a, b].Copy(sheet1.Range[sheet1.LastRow + 1, 1, a + sheet1.LastRow, b]);
workbook1.SaveToFile("reslut.xlsx", ExcelVersion.Version2013);
I have already tried the code and it works well on my side.
I created an excel file dynamicly using openXML. Inside this sheet there are multiple sheets. Inside each sheet there can be rows that are write-protected.
I use an excel file as template. In this template there are "normal" rows which allow editing and a row that does not. I grab the row and copy it to the places where I do not want the user to be able to edit the contents:
private Row CloneRow(Row sourceRow, uint index, bool? hidden = null)
{
var targetRow = (Row) sourceRow.CloneNode(true);
if (hidden.HasValue)
{
targetRow.Hidden = hidden;
}
foreach (Cell cell in targetRow.Elements<Cell>())
{
// Update the references for reserved cells.
string cellReference = cell.CellReference.Value;
cell.CellReference = new StringValue(cellReference.Replace(targetRow.RowIndex.Value.ToString(), index.ToString()));
cell.CellFormula = null;
}
// Update the row index.
targetRow.RowIndex = new UInt32Value(index);
return targetRow;
}
the parameter sourceRow is read from the template:
List<Row> rows = sheet.ChildElements.OfType<Row>().ToList();
rowChangeAllowed=rows.FirstOrDefault(rw=>rw.RowIndex==3);
rowNotChangeAllowed=rows.FirstOrDefault(rw=>rw.RowIndex==4);
Everything works as expected. But when I open the file in Excel, rows that should be proteced on ANY sheet are protected on ALL sheets.
Example:
Sheet 1: Row 4+5 should be protected
Sheet 2: Row 7 should be protected.
Now on sheet 1 rows 4,5 and 7 are protected
When I switch to the second sheet, suddenly everything works as needed: On Sheet 1, row 4+5 are still protected, but row 7 is not.
Because the behaviour is only wrong directly after opening the file, but is correct when I switch between the sheets: Is there an additional command I have to call to "refresh" the file after creating?
Additional Issue:
When I change a cell in sheet 1, it also is automaticly changed in sheet 2 (again: until I swap the sheets once manually)
The problem was having to many views in the sheet. The following code solved the issue:
//There can only be one sheet that has focus
SheetViews views = worksheetPart.Worksheet.GetFirstChild<SheetViews>();
if (views != null)
{
views.Remove();
worksheetPart.Worksheet.Save();
}
(got it from http://blogs.msdn.com/b/brian_jones/archive/2009/02/19/how-to-copy-a-worksheet-within-a-workbook.aspx)
I am creating an application to retrieve the column names into listbox from a particular excel sheet and match the column names with the database columns and insert it into the excel data into table
Can you explain how can I can do it?
Already I have retrieved sheet names into the list box
Microsoft.Office.Interop.Excel.Application app = new ApplicationClass();
Workbook workBook = app.Workbooks.Open(#"your_file_path");
Worksheet workSheet = (Worksheet)workBook.Worksheets.get_Item(1);
Range range = workSheet.UsedRange;
for (int i = 1; i <= range.Columns.Count; i++)
{
ListBox3.Items.Add(((Excel.Range)range.Cells[2, i]).Value2);
}
See How to convert a- column number eg. 127 into an Excel column eg. AA here on Stackoverflow
I'm trying to read data from a multiple sheet excel file.
The first sheet has column headers. the second sheet does not. and the third one does not have any. I can successfully read from the first sheet.
When i try reading from the sheet without header, the program throughs an exception.
var sheet1_data = from c in excel.Worksheet<Species>("Sheet1") select c; // This works and the question is how do i retreive data from sheet2?
I'm currently using this:
var Sheet2_data = from b in excel.WorksheetNoHeader("sheet2") select b;
When i try and read from sheet2_data, i get the following exception:
'sheet2' is not a valid worksheet name. Valid worksheet names are: 'sheet2,sheet3',
Any help will be highly appreciated.
B.
the sheet name can be abstract using GetWorksheetNames() method.
var sheets = excel.GetWorksheetNames();
foreach(var sheet in sheets)
{
var sheetData = from x in excel.Worksheet(sheet) select x;
}