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;
}
}
}
Related
So this is my Program
You can add as much rows as you want to this gridview and when you press the 'Ready' button the program watches your input via the KeyDown-Event.
When you press one of those Hotkeys shown in the gridview you get all the songs which are in the matching path.
I thought I could do something like this:
switch (e.KeyValue.ToString().Substring(0, 0))
{
foreach (DataGridViewRow item in grdView)
{
case item.Cells[2].Value:
//Get all the songs
break;
}
}
Unfortunatelly I get tons of errors. I guess it won't work like this.
Is there any other way to ask for all Hotkeys written in the gridview?
Thanks for any kind of advice.
foreach (DataGridViewRow item in grdView)
{
if(item.Cells[2].Value == theValueYouAreLookingFor)
{
// Do something here
break;
}
}
And also e.KeyValue.ToString().Substring(0, 0) doesn't look right, I'm pretty sure that it isn't going to do quite what you want it to do.
Although iterating through all items with foreach and checking for equals would work,
I thought its worth to mention few alternative in case someone finds it in the future:
one is Linq:
var itemFound = grdView.FirstOrDefault(item => item.Cells[2].Value == theValueYouAreLookingFor);
if (itemFound == null)
{
//no items found in this case
}
the other is Dictionary which is a more efficient solution to map dynamic amount of options in general, but it you'll have to build it beforehand:
simple build example (do this when the grid is created/changed):
shortcutsMap = grdView.ToDictionary(item => item.Cells[2].Value, item);
get:
var itemFound = shortcutsMap[theValueYouAreLookingFor] //will throw exception if not found
or:
shortcutsMap.TryGetValue(theValueYouAreLookingFor, out var itemFound) //returns true/false if found and result will be at itemFound
Using C# .NET 4.5, MS visual studio 2012, WPFs.
Hi, just got this code to finally work, it basically iterates through a datgrid via row.
be warned his may offend all the WPF wizards out there!
public IEnumerable<System.Windows.Controls.DataGridRow> GetDataGridRow(System.Windows.Controls.DataGrid grid)
{
var itemsource = grid.ItemsSource as System.Collections.IEnumerable;
paretogrid.UpdateLayout();
if (null == itemsource) yield return null;
foreach (var item in itemsource)
{
var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow; // null?
if (null != row) yield return row;
}
}
private void ShowArrows()
{
var rows = GetDataGridRow(paretogrid); // fetching null?
foreach (DataGridRow r in rows)
{
DataRowView rv = (DataRowView)r.Item;
}
}
So as you can see I iterate through the rows. Now what I want to do is compare a cell value at column index 2 with columns index 4 on every "row", then if true or false update column 5 accordingly. I can iterate through the columns which lets me go cell per cell but isn't what I am after e.g
foreach (DataGridColumn column in paretogrid.Columns)
So is it something like:
paretogrid.Columns[2].GetCellContent(something here) as textblock;
please see the following explanation below it will help clear up why you are seeing what you are seeing
Ok let me make it easier for you to understand TextBox for example if I did:
var myInt = (int)textBox1.text;
for example this would compile because I am implying that I want myInt to store an Int32 value, however :
var myInt = (int)textBox1;
would fail because you can not convert an Object, which is the TextBox to a Value does this make it easier to see where your initial error is an why you were getting it.
This also has nothing to do with WinForms vs WPF if basically something simple that I am sure many of us have done before because we forget to Append .Text to the end of the object when we are wanting to convert the Value that the object holds rather that the object itself
Turns out I over thought this. here's the solution I had,
var test1 = paretogrid.Columns[7].GetCellContent(paretogrid.Items[2]) as TextBlock;
int t1convert = Convert.ToInt32(test1.Text);
var test2 = paretogrid.Columns[8].GetCellContent(paretogrid.Items[2]) as TextBlock;
int t2convert = Convert.ToInt32(test2.Text);
if (t1convert == t2convert)
{
MessageBox.Show("it worked!");
}
Thanks for pointing this out #DJ KRAZE
Hi there I have searched for a while now and can't seem to find a solution to my problem, I have tried multiple methods to select multiple items in my listbox through code however none have worked, The best result I got was 1 selected item in my listbox.
Basically I want to select multiple items of the same value.
below is my code, sorry if I seem newbie but I am new to programming and still learning basic stuff.
foreach (string p in listBox1.Items)
{
if (p == searchstring)
{
index = listBox1.Items.IndexOf(p);
listBox1.SetSelected(index,true);
}
}
So as you can see I am trying to tell the program to loop through all the items in my listbox, and for every item that equals "searchstring" get the index and set it as selected.
However all this code does is select the first item in the list that equals "searchstring" makes it selected and stops, it doesn't iterate through all the "searchstring" items.
As suggested in the comment, you should set SelectionMode to either MulitSimple or MultiExpanded depending on your needs, but you also need to use for or while loop instead offoreach, because foreach loop doesn't allow the collection to be changed during iterations. Therefore, even setting this Property won't make your code run and you will get the exception. Try this:
for(int i = 0; i<listBox1.Items.Count;i++)
{
string p = listBox1.Items[i].ToString();
if (p == searchstring)
{
listBox1.SetSelected(i, true);
}
}
You can set SelectionMode either in the Properties window when using designer or in, for instance, constructor of your Form using this code:
listBox1.SelectionMode = System.Windows.Forms.SelectionMode.MultiSimple;
I have user submitted content that is loaded into c# winform in our office for processing before officially added to database. The user can submit a 'Referrer' as two text fields-first and last name. In the office I want to have a combobox will all existing referrers loaded in, then the first couple letters of the name to advance the combobox down to the area it needs to be at. I want to do something like this, taking the first two letters of the name and use that to initialize the combobox.
if (txtrefFirstName.TextLength > 2)
{
string firstStart = "" + txtrefFirstName.Text[0] + txtrefFirstName.Text[1];
firstStart = firstStart.ToUpper();
ddlReferring.SelectedText.StartsWith(firstStart);
}
else
ddlReferring.Text = "";
Any ideas or suggestions to get this to work?
Thanks
David K.
You could write something like this...
foreach (string item in ddlReferring.Items)
{
if (item.StartsWith(firstStart))
{
ddlReferring.SelectedText = item;
break;
}
}
Assuming the ddl's datasource is a List of String objects, you should be able to do some comparison on the datasource itself. I tend to use Linq for things like this but it isn't strictly necessary, just shorter.
if (txtrefFirstName.TextLength > 2)
{
string firstStart = txtrefFirstName.Text.Substring(0,2).ToUpper();
string Selection = ddlReferring.DataSource.Where(a=>a.StartsWith(firstStart)).FirstOrDefault();
ddlReferring.SelectedText = Selection ?? "";
}
else
ddlReferring.Text = "";
The selection line can also come from the items collection directly
string Selection = ddlReferring.Items.OfType<string>().Where(a=>a.StartsWith(firstStart)).FirstOrDefault();
Or if you REALLY dont want to use Linq...
string Selection = "";
foreach (object item in ddlReferring.Items)
if (item.ToString().StartsWith(firstStart))
{
Selection = item.ToString();
break;
}
Similar methods can be used even if the ddl's data is not a list of strings, just make sure to cast the items appropriately and compare the correct values.
I have a DataGridView.
I can click the column headers to sort the data by whichever column header I click.
I have some functionality that clears the DataGridView, and repopulates it with data. The problem I'm having is that the indication of a sort in a particular column (the gray upside up or upside down triangle) still remains even though the data isn't sorted by that column because it was just loaded into the DataGridView.
Is there any way I can reapply the sort right after the new data is added?
Edit: If this isn't very easy, just being able to get rid of that gray upside-up or upside-down triangle is good enough so it is clear that the data is not sorted.
This should do the remove
Column.HeaderCell.SortGlyphDirection = SortOrder.None;
But if you read this, you should be able to extract what you need ?
http://msdn.microsoft.com/en-us/library/ms171608.aspx
Before you repopulate, take a note of the sorted column, and afterwards reapply the sort: you might also want to preserve the current selected row, as otherwise it will be lost when you repopulate.
int? index = null;
int firstDisplayedRowIndex = 0;
int sortedColumnIndex = -1;
SortOrder sortOrder = SortOrder.Ascending;
if (dgv.CurrentRow != null)
{
index = dgv.CurrentRow.Index;
firstDisplayedRowIndex = dgv.FirstDisplayedScrollingRowIndex;
if (dgv.SortedColumn != null)
{
sortedColumnIndex = dgv.SortedColumn.Index;
sortOrder = dgv.SortOrder;
}
}
// Repopulate grid...
if (index.HasValue)
{
if (sortedColumnIndex > -1)
{
switch (sortOrder)
{
case SortOrder.Ascending:
dgv.Sort(dgv.Columns[sortedColumnIndex], ListSortDirection.Ascending);
break;
case SortOrder.Descending:
dgv.Sort(dgv.Columns[sortedColumnIndex],
ListSortDirection.Descending);
break;
// SortOrder.None - or anthing else - do nothing
}
}
dgv.Rows[index.Value].Selected = true;
dgv.Rows[index.Value].Cells[0].Selected = true;
dgv.FirstDisplayedScrollingRowIndex = firstDisplayedRowIndex;
// Call any code that needs to know the selection might have changed
}