e.g. a user selects multiple worksheets in a workbook using CTRL+Click. How can I determine which worksheets are selected and which not? I was playing around with that but I couldn't find any useful property to check.
Excel.Sheets abc = Globals.ThisAddIn.Application.ActiveWorkbook.Worksheets;
foreach (Excel.Worksheet sheet in abc)
{
if (sheet.EnableSelection != Excel.XlEnableSelection.xlNoSelection)
{
}
}
I was struggeling around for almost 2 hours. But shortly after I posted this question I found a solution. The ActiveWindow.SelectedSheets delivers what I was looking for.
Excel.Sheets abc = Globals.ThisAddIn.Application.ActiveWindow.SelectedSheets;
foreach (Excel.Worksheet sheet in abc)
{
string asdf = sheet.Name;
}
I haven't knwon the ActiveWindow before.
Still hoping this is useful for someone else, too.
Related
I'm working on an Excel file that I have to convert to an XML file.
Every time I cycle the rows to check if they are empty I use this code:
var ComuniRow = firstRowUsed.RowUsed();
while (!ComuniRow.Cell(coComuneId).IsEmpty())
{
// do stuff;
}
This time tho I need to select a specific row, not the starting one but I have no Idea about how to do that.
Any solutions?
Thanks :)
You can group the rows.
public void UngroupFromAll(){
IXLWorksheet ws = new XLWorkbook().AddWorksheet("Sheet1");
ws.Rows(1, 2).Group();
ws.Rows(1, 2).Ungroup(true);
}
I have a pre-made Excel with PivotTable that gets Data from another worksheet, I fill via c# code.
In the PivotTable there are three Row fields, which after getting populated and the Pivot refreshed via code, make all the rows expanded after opening the Excel.
I already tried using the DrilledDown method (in the fields, but I get an error), the ShowDetails only works in the items (inside the fields).
I got it to work, but it takes too much time because it uses the ShowDetails in each item, is there any other way, and quick for collapsing the fields? (opening the Excel and doing it manually is not an option).
My Code (which collapses the fields are):
listItems.Add("Data");
listItems.Add("Months");
listItems.Add("Grocery");
Microsoft.Office.Interop.Excel.PivotFields pfs = (Microsoft.Office.Interop.Excel.PivotFields)pivot.PivotFields();
foreach (String s in listItems)
{
Microsoft.Office.Interop.Excel.PivotField pf = (Microsoft.Office.Interop.Excel.PivotField)pivot.PivotFields(s);
foreach (Microsoft.Office.Interop.Excel.PivotItem item in (Microsoft.Office.Interop.Excel.PivotItems)pf.PivotItems())
{
if (item.Value == "(blank)")
item.Visible = false;
item.ShowDetail = false;
}
}
The thing is, maybe there's an easy and quicker way? I was trying something like
pf.DrilledDown = False;
or
pf.ShowDetail = False;
But it doesn't work. Any Ideas?
Well, manage from somehow to only collapse the first item in each field (that way the cycle doesn't go until the end, and since Excel collapses automatically the other similar items (when you collapse one of the same type field), it works).
PS: Since the first field from the groceries is allways the "_blank" one, i know for sure there's allways something after the "_blank" one, but I cannot apply only the collapse to the "_blank", because then it doesn't apply to the other items (I supposed it must be something with a Value inside).
So...got this (it's a lot more quick, but still, I think it shall exist another way (with simpler code in c# (without using VB macros inside the Excel)), but if there is, it's hard to find - few people manipulate pivot tables programatically.
listItems.Add("Date");
listItems.Add("Months");
listItems.Add("Groceries");
Microsoft.Office.Interop.Excel.PivotFields pfs = (Microsoft.Office.Interop.Excel.PivotFields)pivot.PivotFields();
foreach (String s in listItems)
{
Microsoft.Office.Interop.Excel.PivotField pf = (Microsoft.Office.Interop.Excel.PivotField)pivot.PivotFields(s);
foreach (Microsoft.Office.Interop.Excel.PivotItem item in (Microsoft.Office.Interop.Excel.PivotItems)pf.PivotItems())
{
if (pf.Value == "Date")
{
item.ShowDetail = false;
break;
}
if (pf.Value == "Months")
{
item.ShowDetail = false;
break;
}
if (pf.Value == "Groceries")
{
if (item.Value == "(blank)")
{
item.Visible = false;
continue;
}
item.ShowDetail = false;
break;
}
}
}
In my Workbook, I have 4 worksheets with different tab names.
Say if they are named as follows: First, Second, Third, Fourth.
I could not find online how to iterate through each of the worksheet with say for for loop. As I am iterating, I would also like to capture the text on the Worksheet's tab (First, Second, etc.).
You can either grab the worksheets by name or id such as:
int index = 1; // note indexes are 1 based in ClosedXML
var worksheet = workbook.Worksheet(index);
string name = "First";
var worksheet = workbook.Worksheet(name);
Note you'll only want to do the above in instances where you know the sheet name and max id (example)
or you can iterate through the collection of worksheets in a workbook as such:
foreach (IXLWorksheet worksheet in workbook.Worksheets)
{
Console.WriteLine(worksheet.Name); // outputs the current worksheet name.
// do the thing you want to do on each individual worksheet.
}
You can find this information in visual studio by hitting F12 on your workbook object, you'll see all of the public methods/variables you're given access too. IXLWorksheet and IXLWorksheets is what you're looking for.
I am creating a ListObject in Excel using VSTO as follows:
ListObject lo = ws_vsto.Controls.AddListObject(range, "MyList");
(The range variable is a previously defined range.)
If I then loop through the worksheet Controls collection I can find that ListObject.
However, if I save the workbook and reopen it, the Controls collection is empty. How can I get this ListObject back after re-opening so that I can continue working with it?
EDIT
I've got a bit further:
var wb = Globals.ThisAddIn.Application.ActiveWorkbook;
var wb_vsto = wb.GetVstoObject();
foreach (Excel.Worksheet ws in wb.Worksheets)
{
var wsv = ws.GetVstoObject();
foreach (Excel.ListObject l in ws.ListObjects)
{
MessageBox.Show(l.Name);
var lo = wsv.Controls.AddListObject(l);
Excel.Range range = lo.Range;
range.Activate();
}
}
When I get to the var lo = line, I have a ListObject added to the Controls collection and available for use. However, it's DataSource property holds null. Is there an easy way to get the original data source back?
I then thought about rebuilding the data source from the information in the range. The range.Activate() line selects the list in Excel (so I know it has the right thing). However, I can't for the life of me work out how to get the data out of that range and get the address of the range. The MSDN documentation talks about the Address property but this doesn't appear to actually exist. (MSDN documentation for VSTO seems ropey at best).
I made the following changes to the initial code. You need to get a VSTO Listobject back from the Factory.
var wb = Globals.ThisAddIn.Application.ActiveWorkbook;
var wb_vsto = wb.GetVstoObject();
foreach (Excel.Worksheet ws in wb.Worksheets)
{
var wsv = ws.GetVstoObject();
foreach (Excel.ListObject l in ws.ListObjects)
{
MessageBox.Show(l.Name);
//var lo = wsv.Controls.AddListObject(l);
Microsoft.Office.Tools.Excel.ListObject lo =
Globals.Factory.GetVstoObject(l);
// I can now get at the datasource if neede
var ds = lo.DataSource;
// In my case the datasource was DataTable.
DataTable t = (DataTable)d;
if (t.Rows.Count > 0)
{
foreach (DataRow r in t.Rows)
{
// Access row data.
}
}
//Excel.Range range = lo.Range;
//range.Activate();
}
}
Have you tried?
Microsoft.Office.Tools.Excel.ListObject lo= Microsoft.Office.Tools.Excel.ListObject.GetVstoObject(l) (it's C# I'm not sure in VB)
From MSDN GetVstoObject, be sure to read the remarks.
About your first question,
you created the listOject with the code
ListObject lo = ws_vsto.Controls.AddListObject(range, "MyList");
To recover the object after save/reope the workbook, try this line of code:
ListObject lo = Globals.Factory.GetVstoObject(Worksheet.ListObjects["MyList"]);
You simply can't get back a ListObject control that you created dynmically during run-time. this is from the MSDN documentation.
By default, dynamically created list objects are not persisted in the
worksheet as host controls when the worksheet is closed.
The only way I can get back my ListObject is to create them directly in the sheets of my template during design-time.
I'm using Excel Interop assemblies for my project,
if I want to use auto filter with then thats possible using
sheet.UsedRange.AutoFilter(1,SheetNames[1],Microsoft.Office.Interop.Excel.XlAutoFilterOperator.xlAnd,oMissing,false)
but how can I get the filtered rows ??
can anyone have idea??
Once you filtered the range, you can access the cells that pass the filter criteria by making use of the Range.SpecialCells method, passing in a valued of 'Excel.XlCellType.xlCellTypeVisible' in order to get the visible cells.
Based on your example code, above, accessing the visible cells should look something like this:
Excel.Range visibleCells = sheet.UsedRange.SpecialCells(
Excel.XlCellType.xlCellTypeVisible,
Type.Missing)
From there you can either access each cell in the visible range, via the 'Range.Cells' collection, or access each row, by first accessing the areas via the 'Range.Areas' collection and then iterating each row within the 'Rows' collection for each area. For example:
foreach (Excel.Range area in visibleCells.Areas)
{
foreach (Excel.Range row in area.Rows)
{
// Process each un-filtered, visible row here.
}
}
Hope this helps!
Mike
I used as mentioned below, similar to what Mike told,
foreach (Excel.Range area in visibleCells.Areas)
{
foreach(Excel.Range row in area.Rows)
{
int index = row.Row; // now index is the present Row index within the range
string test = Mysheet.Cells[index,4].Values //// Mysheet is my present working sheet. After this test will contain the values pointing to the values.cells[index,4]
}
}