Create A treenode with List - c#

I have a table in this structure
ListA labelName
1 Colorado
1 Wyoming
1 Illinois
2 New York
2 Ohio
I am trying to create a tree where if LISTA = 1, it goes under one node called "header one" and Colorado, Wyoming, Illinois as its Leaf and samething with value "2"... by doing this I am getting 3 "Header one" nodes instead of having all those three nodes under one...
SqlCommand cmd = con.CreateCommand();
comd.CommandText = "SELECT * FROM myTable";
con.Open();
SqlDataReader reader = comd.ExecuteReader();
while (reader.Read())
{
City MyData = new City();
MyData.ListA = reader["ListA"].ToString().Trim();
MyData.labelName = reader["labelName"].ToString().Trim();
giveData.Add(MyData);
}
int count = 1;
List<TreeNode> myNode = new List<TreeNode>();
foreach (City MyData in giveData)
{
// 1st foreach
if (MyData.ListA != "1")
{
TreeNode treeNode = new TreeNode();
treeNode.id = count++;
treeNode.name = "Header One";
treeNode.leaf = false;
List<TreeNode> Level1 = new List<TreeNode>();
foreach (City labelName in giveData)
{
if (labelName.ListA == "1")
{// 2nd foreach
TreeNode node1 = new TreeNode();
node1.id = count++;
node1.name = labelName.labelName;
node1.leaf = true;
Level1.Add(node1);
}
}
treeNode.children = Level1;
myNode.Add(treeNode);
}
else if (MyData.ListA != "2")
{
TreeNode treeNode = new TreeNode();
treeNode.id = count++;
treeNode.name = "Header Two";
treeNode.leaf = false;
List<TreeNode> Level1 = new List<TreeNode>();
foreach (City labelName in giveData)
{
if (labelName.ListA == "2")
{// 2nd foreach
TreeNode node1 = new TreeNode();
node1.id = count++;
node1.name = labelName.labelName;
node1.leaf = true;
Level1.Add(node1);
}
}
treeNode.children = Level1;
myNode.Add(treeNode);
}
}
return JsonConvert.SerializeObject(myNode);
What would be the best way to handle this

What you need to do is group the data on ListA.
var groups = giveData.GroupBy(state => state.ListA);
foreach(var group in groups)
{
//add header to treeview
string header = group.Key;
foreach(var state in group)
{
//add this state as a child of the group you just added
}
}
I'd also suggest creating a lookup to help you map the ListA number to it's textual representation:
var headerLookup = new Dictionary<string, string>()
{
{"1", "Header One"},
{"2", "Header Two"},
{"3", "Header Three"}
};
This will allow you to do the following:
string headerText = headerLookup[group.Key];

Related

Iterating through a List to show in TreeView

I have four lists that I am trying to get the contents to show up in a TreeView on my Form.
My current problem is that only the last item in each list is showing up in the view.
I am sure it has something to do with how I am iterating through the list but I am pretty stuck on how to get each individual list item to show up in the tree.
My tree structure is:
Dog
Husky
huskylist
Chiwawa
chiwawlist
Cat
Siamese
siameselist
Tabby
tabbylist
My code for the Form where the tree view is:
public partial class Form1 : Form
{
private Model m_modelObj;
public Form1(Model modelObj)
{
InitializeComponent();
m_modelObj = modelObj;
List<Tabby> tabbyList = m_modelObj.TabbyList;
List<Siamese> siameseList = m_modelObj.SiameseList;
List<Husky> huskyList = m_modelObj.HuskyList;
List<Chiwawa> chiwawaList = m_modelObj.ChiwawaList;
//tree code
//add husky list
TreeNode node8 = null;
foreach (var item in huskyList)
{
node8 = new TreeNode(item.name);
}
TreeNode[] husky = new TreeNode[] { node8 };
//add chiwawa list
TreeNode node9 = null;
foreach (var item in chiwawaList)
{
node9 = new TreeNode(item.name);
}
TreeNode[] chiwawa = new TreeNode[] { node9 };
//dog breed
TreeNode node2 = new TreeNode("Husky", husky);
TreeNode node3 = new TreeNode("Chiwawa", chiwawa);
TreeNode[] dog = new TreeNode[] { node2, node3 };
//dog parent
TreeNode treeNode = new TreeNode("Dogs", dog);
treeView1.Nodes.Add(treeNode);
//add tabby list
TreeNode nodes = null;
foreach (var item in tabbyList)
{
nodes = new TreeNode(item.name);
}
TreeNode[] tabby = new TreeNode[] { nodes };
//add siamese list
TreeNode node7 = null;
foreach (var item in siameseList)
{
node7 = new TreeNode(item.name);
}
TreeNode[] siamese = new TreeNode[] { node7 };
//cat breed
TreeNode node4 = new TreeNode("Siamese", siamese);
TreeNode node5 = new TreeNode("Tabby", tabby);
TreeNode[] cat = new TreeNode[] { node4, node5 };
//cat parent
treeNode = new TreeNode("Cats", cat);
treeView1.Nodes.Add(treeNode);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void addDetailsBtn_Click(object sender, EventArgs e)
{
string animalType = comboBoxAnimalType.SelectedItem.ToString();
this.Hide();
PetInfoForm aPetInfoForm = new PetInfoForm(animalType, m_modelObj);
aPetInfoForm.Closed += (s, args) => this.Close();
aPetInfoForm.Show();
}
}
Create Object and Dynamic array in c# Refer here
TreeView Basic to understand Refer here
when you are creating the sub nodes you are overwrite the instance. you should maintain the nodes in a array.
//tree code
//add husky list
List<TreeNode> node8 = new List<TreeNode>();
foreach (var item in huskyList)
{
node8.Add(new TreeNode(item.name));
}
TreeNode[] husky = node8.ToArray();
//add chiwawa list
List<TreeNode> node9 = new List<TreeNode>();
foreach (var item in chiwawaList)
{
node9.Add(new TreeNode(item.name));
}
TreeNode[] chiwawa = node9.ToArray();
//dog breed
TreeNode node2 = new TreeNode("Husky", husky);
TreeNode node3 = new TreeNode("Chiwawa", chiwawa);
TreeNode[] dog = new TreeNode[] { node2, node3 };
//dog parent
TreeNode treeNode = new TreeNode("Dogs", dog);
treeView1.Nodes.Add(treeNode);
//add tabby list
List<TreeNode> nodes = new List<TreeNode>();
foreach (var item in tabbyList)
{
nodes.Add(new TreeNode(item.name));
}
TreeNode[] tabby =nodes.ToArray();
//add siamese list
List<TreeNode> node7 = new List<TreeNode>();
foreach (var item in siameseList)
{
node7.Add(new TreeNode(item.name));
}
TreeNode[] siamese = node7.ToArray();
//cat breed
TreeNode node4 = new TreeNode("Siamese", siamese);
TreeNode node5 = new TreeNode("Tabby", tabby);
TreeNode[] cat = new TreeNode[] { node4, node5 };
//cat parent
treeNode = new TreeNode("Cats", cat);
treeView1.Nodes.Add(treeNode);
Or
Using LINQ you can create the tree like this
// Code Using Linq
TreeNode husky = new TreeNode("Husky", huskyList.Select(x => new TreeNode(x.name)).ToArray());
TreeNode chiwawa = new TreeNode("Chiwawa", chiwawaList.Select(x => new TreeNode(x.name)).ToArray());
TreeNode Siamese = new TreeNode("Siamese", siameseList.Select(x => new TreeNode(x.name)).ToArray());
TreeNode Tabby = new TreeNode("Tabby", tabbyList.Select(x => new TreeNode(x.name)).ToArray());
//parent nodes
treeView1.Nodes.AddRange(new[] {
new TreeNode("Dog", new TreeNode[] { husky, chiwawa }),
new TreeNode("Cat", new TreeNode[] { Siamese, Tabby })
});

C# TreeViewAdv get selected node's value

I am using syncfusion's TreeViewAdv in multi column mode.
I am trying to get the selected node's value (from the first column) but I have not been successful.
Has anyone been able to do this?
Many thanks
Edit:
A quick update on how I am populating the control
private void RefreshOptions()
{
List<String> objects = Globals.ThisAddIn.utilities.ListRObjectsWithDetail();
StringBuilder name = new StringBuilder(100);
StringBuilder details = new StringBuilder(200);
Node dataRootNode = new Node();
Node dataParentNode = new Node();
Node dataChildNode1 = new Node();
Node dataChildNode2 = new Node();
Node dataChildNode3 = new Node();
Node functionsRootNode = new Node();
Node functionsParentNode = new Node();
int charLocation;
int indexChild;
int childLevel;
TreeModel _model = new TreeModel();
treeViewAdv1.Model = _model;
treeViewAdv1.BeginUpdate();
dataRootNode = new ColumnNode("Data / Values", "", "");
_model.Nodes.Add(dataRootNode);
functionsRootNode = new ColumnNode("Functions", "", "");
_model.Nodes.Add(functionsRootNode);
foreach (String obj in objects)
{
name.Clear();
details.Clear();
name.Append(obj.Trim());
charLocation = name.ToString().IndexOf(":");
details.Append(name.ToString().Substring(charLocation + 1).Trim());
name.Length = charLocation;
if (details.Length >=10 && details.ToString(0, 10) == "function (")
{
functionsParentNode = new ColumnNode(name.ToString(), "Function", details.ToString());
functionsRootNode.Nodes.Add(functionsParentNode);
}
else
{
indexChild = name.ToString().IndexOf("$");
if (indexChild > -1)
{
childLevel = name.ToString(0, indexChild).Split('.').Length - 1;
name.Remove(0, 1 + childLevel);
switch (indexChild)
{
case 1:
dataChildNode1 = new ColumnNode(name.ToString(), "Data / Value", details.ToString());
dataParentNode.Nodes.Add(dataChildNode1);
break;
case 2:
dataChildNode2 = new ColumnNode(name.ToString(), "Data / Value", details.ToString());
dataChildNode1.Nodes.Add(dataChildNode2);
break;
case 3:
dataChildNode3 = new ColumnNode(name.ToString(), "Data / Value", details.ToString());
dataChildNode2.Nodes.Add(dataChildNode3);
break;
}
}
else
{
dataParentNode = new ColumnNode(name.ToString(), "Data / Value", details.ToString());
dataRootNode.Nodes.Add(dataParentNode);
}
}
}
NodeTextBox ntb = new NodeTextBox();
ntb.DataPropertyName = "Text";
this.treeViewAdv1.NodeControls.Add(ntb);
treeViewAdv1.EndUpdate();
}
I spent some time looking at the TreeViewAdv sample project. Specifically I looked the "FolderBrowser.cs" winform which did have the below NodeMouseDoubleClick event. This correctly wrote the node tot he console.
private void _treeView_NodeMouseDoubleClick(object sender, TreeNodeAdvMouseEventArgs e)
{
Console.WriteLine(e.Node);
}
If I use exactly the same event then my e.Node = "" although my node is fully populated.

How to prevent it from being added 2 times in listview

I ama getting data from news website with webrequest and show my listview. When user click button , first of all I am getting all news and show my listview, after e.g 15 min user click button again. I am checking my news list if news is exits, I am showing messagebox "There is no fresh news". but if there is a news put all news list in listview again. For example. first lisview count is 75 . and there is 2 fresh news, normally my listview should 77. but listview shows 152. Where is my mistake. can you help me ?
my button click event
private void btnHurriyet_Click(object sender, EventArgs e)
{
Hurriyet hurriyet = new Hurriyet();
List<ListViewItem> list = hurriyet.GetTagsHurriyet();
foreach (var item in list)
{
listView1.Items.Add(item);
}
}
this is my class
public static Dictionary<string, Hurriyet> HurriyetHaberList = new Dictionary<string, Hurriyet>();
public List<ListViewItem> GetTagsHurriyet()
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load("http://www.hurriyet.com.tr/rss/gundem");
XmlElement el = (XmlElement)xdoc.SelectSingleNode("/rss");
if (el != null)
{
el.ParentNode.RemoveChild(el);
}
XmlNode Haberler = el.SelectSingleNode("channel");
List<ListViewItem> listViewItems = new List<ListViewItem>();
bool degismiMi = false;
foreach (XmlNode haber in Haberler.SelectNodes("item"))
{
Hurriyet h = new Hurriyet();
ListViewItem li = new ListViewItem();
//li.Text = haber.SelectSingleNode("title").InnerText;
h.Title = haber.SelectSingleNode("title").InnerText;
if (haber.SelectSingleNode("description").InnerText.Contains(">"))
{
var str1 = haber.SelectSingleNode("description").InnerText.IndexOf(">");
var str2 = haber.SelectSingleNode("description").InnerText.Substring(str1 + 4);
//li.SubItems.Add(str2);
}
else
{
//li.SubItems.Add(haber.SelectSingleNode("description").InnerText);
h.Description = haber.SelectSingleNode("description").InnerText;
}
h.Link = haber.SelectSingleNode("link").InnerText;
//li.SubItems.Add(haber.SelectSingleNode("link").InnerText);
var format = DateTime.Parse(haber.SelectSingleNode("pubDate").InnerText.ToString());
//li.SubItems.Add(format.ToString());
h.PubDate = format;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(haber.SelectSingleNode("link").InnerText);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader stream = new StreamReader(response.GetResponseStream());
string final_response = stream.ReadToEnd();
string begenningKeyword = "<meta name=\"keywords\" content=\"";
var tags = final_response.IndexOf(begenningKeyword);
var final_response2 = final_response.Substring(tags + begenningKeyword.Length);
var tagsBol = final_response2.IndexOf("\" />");
var lastTags = final_response2.Substring(0, tagsBol);
int yer1;
if (lastTags != string.Empty)
{
h.Tags = lastTags;
//li.SubItems.Add(lastTags);
}
else
{
yer1 = final_response.IndexOf("tagsContainer");
if (yer1 == -1)
{
continue;
}
else
{
yer1 = final_response.IndexOf("tagsContainer");
int yer2 = final_response.IndexOf("</div>", yer1);
var tagDiv = final_response.Substring(yer1, yer2 - yer1);
List<string> listele = new List<string>();
for (int i = 0; i < tagDiv.Length; i++)
{
var firstSpan = tagDiv.IndexOf("<span>");
var firstSpan2 = tagDiv.IndexOf("<span itemprop=\"keywords\">");
if (firstSpan != -1)
{
var secondSpan = tagDiv.IndexOf("</a>", firstSpan);
var lastSpan = tagDiv.Substring(firstSpan, secondSpan - firstSpan);
var remo = lastSpan.Replace("<span>", "");
var remo2 = remo.Replace("</span>", "");
listele.Add(remo2);
tagDiv = tagDiv.Replace(lastSpan, "");
}
else if (firstSpan2 != -1)
{
var secondSpan = tagDiv.IndexOf("</a>", firstSpan2);
var lastSpan = tagDiv.Substring(firstSpan2, secondSpan - firstSpan2);
var remo = lastSpan.Replace("<span itemprop=\"keywords\">", "");
var remo2 = remo.Replace("</span>", "");
listele.Add(remo2);
tagDiv = tagDiv.Replace(lastSpan, "");
}
else
break;
}
string c = string.Empty;
foreach (var item in listele)
{
c += item + ",";
}
//li.SubItems.Add(c.Substring(0, c.Length - 1));
h.Tags = c.Substring(0, c.Length - 1);
}
}
if (HurriyetHaberList.ContainsKey(haber.SelectSingleNode("link").InnerText) == false)
{
HurriyetHaberList.Add(haber.SelectSingleNode("link").InnerText, h);
degismiMi = true;
//listViewItems.Insert(0,li);
}
}
if (!degismiMi)
{
MessageBox.Show("Haberlerde değişiklik olmadı");
}
else
{
listViewItems.Clear();
foreach (var item in HurriyetHaberList.OrderByDescending(x => x.Value.PubDate).ToList())
{
ListViewItem lstItem = new ListViewItem();
lstItem.Text = item.Value.Title;
lstItem.SubItems.Add(item.Value.Description);
lstItem.SubItems.Add(item.Value.Link);
lstItem.SubItems.Add(item.Value.PubDate.ToString());
lstItem.SubItems.Add(item.Value.Tags);
listViewItems.Add(lstItem);
}
}
return listViewItems;
}
Screenshot
The problem is that your code
hurriyet.GetTagsHurriyet();
Delivers all 77 Items and this result is than added to your list Control with the below code
foreach (var item in list)
{
listView1.Items.Add(item);
}
You need to clear your listView1 or make sure that the method GetTagsHurriyet() only returns new items.
So either do the following:
private void btnHurriyet_Click(object sender, EventArgs e)
{
Hurriyet hurriyet = new Hurriyet();
List<ListViewItem> list = hurriyet.GetTagsHurriyet();
listView1.Items.Clear(); //<-- added line
foreach (var item in list)
{
listView1.Items.Add(item);
}
}
Or in your GetTagsHurriyet() method only fill the list if your dictionary says it is new:
if (HurriyetHaberList.ContainsKey(haber.SelectSingleNode("link").InnerText) == false)
{
HurriyetHaberList.Add(haber.SelectSingleNode("link").InnerText, h);
degismiMi = true;
//listViewItems.Insert(0,li);
//add items to listViewItems here and drop the code below
}
Edit:
Based on the comment below:
Something like this:
(Didnt test the code, removed some comments to make it smaller also changed some stuff here and there)
private void btnHurriyet_Click(object sender, EventArgs e)
{
Hurriyet hurriyet = new Hurriyet();
List<ListViewItem> list = hurriyet.GetTagsHurriyet();
if (!list.Any())
MessageBox.Show("Haberlerde değişiklik olmadı");
else
{
foreach (var item in list)
listView1.Items.Add(item);
}
}
public static Dictionary<string, Hurriyet> HurriyetHaberList = new Dictionary<string, Hurriyet>();
public List<ListViewItem> GetTagsHurriyet()
{
XmlDocument xdoc = new XmlDocument();
xdoc.Load("http://www.hurriyet.com.tr/rss/gundem");
XmlElement el = (XmlElement)xdoc.SelectSingleNode("/rss");
if (el != null)
el.ParentNode.RemoveChild(el);
XmlNode Haberler = el.SelectSingleNode("channel");
List<Hurriyet> newHurriyets = new List<Hurriyet>();
bool degismiMi = false;
foreach (XmlNode haber in Haberler.SelectNodes("item"))
{
var link = haber.SelectSingleNode("link").InnerText;
if (HurriyetHaberList.ContainsKey(link))
continue;
Hurriyet h = new Hurriyet();
h.Title = haber.SelectSingleNode("title").InnerText;
if (!haber.SelectSingleNode("description").InnerText.Contains(">"))
h.Description = haber.SelectSingleNode("description").InnerText;
h.Link = link;
var format = DateTime.Parse(haber.SelectSingleNode("pubDate").InnerText.ToString());
h.PubDate = format;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(link);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (StreamReader stream = new StreamReader(response.GetResponseStream()))
{
string final_response = stream.ReadToEnd();
string begenningKeyword = "<meta name=\"keywords\" content=\"";
var tags = final_response.IndexOf(begenningKeyword);
var final_response2 = final_response.Substring(tags + begenningKeyword.Length);
var tagsBol = final_response2.IndexOf("\" />");
var lastTags = final_response2.Substring(0, tagsBol);
int yer1;
if (!string.IsNullOrEmpty(lastTags))
h.Tags = lastTags;
else
{
yer1 = final_response.IndexOf("tagsContainer");
if (yer1 == -1)
continue;
yer1 = final_response.IndexOf("tagsContainer");
int yer2 = final_response.IndexOf("</div>", yer1);
var tagDiv = final_response.Substring(yer1, yer2 - yer1);
List<string> listele = new List<string>();
for (int i = 0; i < tagDiv.Length; i++)
{
var firstSpan = tagDiv.IndexOf("<span>");
var firstSpan2 = tagDiv.IndexOf("<span itemprop=\"keywords\">");
if (firstSpan != -1)
{
var secondSpan = tagDiv.IndexOf("</a>", firstSpan);
var lastSpan = tagDiv.Substring(firstSpan, secondSpan - firstSpan);
var remo = lastSpan.Replace("<span>", "");
var remo2 = remo.Replace("</span>", "");
listele.Add(remo2);
tagDiv = tagDiv.Replace(lastSpan, "");
}
else if (firstSpan2 != -1)
{
var secondSpan = tagDiv.IndexOf("</a>", firstSpan2);
var lastSpan = tagDiv.Substring(firstSpan2, secondSpan - firstSpan2);
var remo = lastSpan.Replace("<span itemprop=\"keywords\">", "");
var remo2 = remo.Replace("</span>", "");
listele.Add(remo2);
tagDiv = tagDiv.Replace(lastSpan, "");
}
else
break;
}
h.Tags = string.Join(",", listele);
}
}
HurriyetHaberList.Add(link, h);
newHurriyets.Add(h);
}
List<ListViewItem> listViewItems = new List<ListViewItem>();
foreach (var item in newHurriyets.OrderByDescending(x => x.PubDate))
{
ListViewItem lstItem = new ListViewItem();
lstItem.Text = item.Title;
lstItem.SubItems.Add(item.Description);
lstItem.SubItems.Add(item.Link);
lstItem.SubItems.Add(item.PubDate.ToString());
lstItem.SubItems.Add(item.Tags);
listViewItems.Add(lstItem);
}
return listViewItems;
}
You can clear items before filling:
private void btnHurriyet_Click(object sender, EventArgs e)
{
Hurriyet hurriyet = new Hurriyet();
List<ListViewItem> list = hurriyet.GetTagsHurriyet();
listView1.Items.Clear(); // Clear items
foreach (var item in list)
{
listView1.Items.Add(item);
}
}
otherwise you would have to check if listView1 does not have item you want to add (not by reference, maybe some property?). This case however will not handle deleting items
private void btnHurriyet_Click(object sender, EventArgs e)
{
Hurriyet hurriyet = new Hurriyet();
List<ListViewItem> list = hurriyet.GetTagsHurriyet();
foreach (var item in list)
{
if(!IsItemPresent(item)) // You should implement this method somehow
listView1.Items.Add(item);
}
}
listView1 should clear before u add new items. becose their was old data.
put this code listView1.Clear(); before start loop.
listView1.Clear();
private void btnHurriyet_Click(object sender, EventArgs e)
{
Hurriyet hurriyet = new Hurriyet();
List<ListViewItem> list = hurriyet.GetTagsHurriyet();
listView1.Clear();
foreach (var item in list)
{
listView1.Items.Add(item);
}
}

Treeview not adding properly as child

I have the code below to expand the tree node to add childeren to its parents , till the nth level.
Issue : The child is added to the first level always, instead it should have been added till the nth level, to its appropriate parent.
Code below:
public void Populate_Node(Object sender, TreeNodeEventArgs e)
{
// Authenticating
TreeProvider cmsTree = new TreeProvider(MembershipContext.AuthenticatedUser);
//selecting the expanding node
var node = cmsTree.SelectSingleNode(SiteContext.CurrentSiteName, "/Level1-2ndItem", "en-US");
CMS.DocumentEngine.TreeNodeCollection myChildren = node.AllChildren;
//Making array of child treenodes of selected node
IEnumerable<CMS.DocumentEngine.TreeNode> TreeNodes = myChildren.AsEnumerable<CMS.DocumentEngine.TreeNode>();
foreach (var tree in myChildren)
{
System.Web.UI.WebControls.TreeNode ParenTreeNode = new System.Web.UI.WebControls.TreeNode();
ParenTreeNode.Text = tree.NodeID.ToString() + ". " + SiteContext.CurrentSiteName;
ParenTreeNode.Value = tree.NodeID.ToString();
AddExpandedNodes(ParenTreeNode);
}
}
private void AddExpandedNodes(System.Web.UI.WebControls.TreeNode TreeNode)
{
CMS.DocumentEngine.TreeProvider cmsTree = new CMS.DocumentEngine.TreeProvider(CMS.Membership.MembershipContext.AuthenticatedUser);
var node = cmsTree.SelectSingleNode(CMS.SiteProvider.SiteContext.CurrentSiteName, "/", "en-US");
CMS.DocumentEngine.TreeNodeCollection myChildren = node.AllChildren;
IEnumerable<CMS.DocumentEngine.TreeNode> childTreeNodes = myChildren.AsEnumerable<CMS.DocumentEngine.TreeNode>().Where(x => x.NodeParentID == Convert.ToInt32(TreeNode.Value));
foreach (var childTree in childTreeNodes)
{
System.Web.UI.WebControls.TreeNode ChildNode = new System.Web.UI.WebControls.TreeNode();
ChildNode.Text = childTree.NodeID.ToString() + ". " + childTree.DocumentName.ToString();
ChildNode.Value = childTree.NodeID.ToString();
ChildNode.ChildNodes.Add(ChildNode);
AddExpandedNodes(ChildNode);
tvContentTree.Nodes.Add(ChildNode);
}
}

Create Pivot Table Filters With EPPLUS

I am using EPPLUS excel library. Do you have an idea how to create pivot table with report filters, row label and values ? Some simple example will be excellent.
Here is a simple example. Note that EEPlus does not have the ability to do page filters so you will have to use (in order of difficulty) VBA, Excel Interop, or XML manipulation (I used XML below). You can put this code into a unit test of the EPPlus source download for easy testing:
const string FORMATCURRENCY = "#,###;[Red](#,###)";
var file = new FileInfo(#"c:\temp\temp.xlsx");
if (file.Exists)
file.Delete();
var pck = new ExcelPackage(file);
var workbook = pck.Workbook;
var worksheet = workbook.Worksheets.Add("newsheet");
//The data
worksheet.Cells["A20"].Value = "Col1";
worksheet.Cells["A21"].Value = "sdf";
worksheet.Cells["A22"].Value = "wer";
worksheet.Cells["A23"].Value = "ghgh";
worksheet.Cells["A24"].Value = "sdf";
worksheet.Cells["A25"].Value = "wer";
worksheet.Cells["A26"].Value = "ghgh";
worksheet.Cells["A27"].Value = "sdf";
worksheet.Cells["A28"].Value = "wer";
worksheet.Cells["A29"].Value = "ghgh";
worksheet.Cells["B20"].Value = "Col2";
worksheet.Cells["B21"].Value = "Group A";
worksheet.Cells["B22"].Value = "Group B";
worksheet.Cells["B23"].Value = "Group A";
worksheet.Cells["B24"].Value = "Group C";
worksheet.Cells["B25"].Value = "Group A";
worksheet.Cells["B26"].Value = "Group B";
worksheet.Cells["B27"].Value = "Group C";
worksheet.Cells["B28"].Value = "Group C";
worksheet.Cells["B29"].Value = "Group A";
worksheet.Cells["C20"].Value = "Col3";
worksheet.Cells["C21"].Value = 453;
worksheet.Cells["C22"].Value = 634;
worksheet.Cells["C23"].Value = 274;
worksheet.Cells["C24"].Value = 453;
worksheet.Cells["C25"].Value = 634;
worksheet.Cells["C26"].Value = 274;
worksheet.Cells["C27"].Value = 453;
worksheet.Cells["C28"].Value = 634;
worksheet.Cells["C29"].Value = 274;
worksheet.Cells["D20"].Value = "Col4";
worksheet.Cells["D21"].Value = 686468;
worksheet.Cells["D22"].Value = 996440;
worksheet.Cells["D23"].Value = 185780;
worksheet.Cells["D24"].Value = 686468;
worksheet.Cells["D25"].Value = 996440;
worksheet.Cells["D26"].Value = 185780;
worksheet.Cells["D27"].Value = 686468;
worksheet.Cells["D28"].Value = 996440;
worksheet.Cells["D29"].Value = 185780;
//The pivot table
var pivotTable = worksheet.PivotTables.Add(worksheet.Cells["A4"], worksheet.Cells["A20:D29"], "test");
//The label row field
pivotTable.RowFields.Add(pivotTable.Fields["Col1"]);
pivotTable.DataOnRows = false;
//The data fields
var field = pivotTable.DataFields.Add(pivotTable.Fields["Col3"]);
field.Name = "Sum of Col2";
field.Function = DataFieldFunctions.Sum;
field.Format = FORMATCURRENCY;
field = pivotTable.DataFields.Add(pivotTable.Fields["Col4"]);
field.Name = "Sum of Col3";
field.Function = DataFieldFunctions.Sum;
field.Format = FORMATCURRENCY;
//The page field
pivotTable.PageFields.Add(pivotTable.Fields["Col2"]);
var xdCacheDefinition = pivotTable.CacheDefinition.CacheDefinitionXml;
var xeCacheFields = xdCacheDefinition.FirstChild["cacheFields"];
if (xeCacheFields == null)
return;
//To filter, add items to the Cache Definition via XML
var count = 0;
var assetfieldidx = -1;
foreach (XmlElement cField in xeCacheFields)
{
var att = cField.Attributes["name"];
if (att != null && att.Value == "Col2" )
{
assetfieldidx = count;
var sharedItems = cField.GetElementsByTagName("sharedItems")[0] as XmlElement;
if(sharedItems == null)
continue;
//set the collection attributes
sharedItems.RemoveAllAttributes();
att = xdCacheDefinition.CreateAttribute("count");
att.Value = "3";
sharedItems.Attributes.Append(att);
//create and add the item
var item = xdCacheDefinition.CreateElement("s", sharedItems.NamespaceURI);
att = xdCacheDefinition.CreateAttribute("v");
att.Value = "Group A";
item.Attributes.Append(att);
sharedItems.AppendChild(item);
item = xdCacheDefinition.CreateElement("s", sharedItems.NamespaceURI);
att = xdCacheDefinition.CreateAttribute("v");
att.Value = "Group B";
item.Attributes.Append(att);
sharedItems.AppendChild(item);
item = xdCacheDefinition.CreateElement("s", sharedItems.NamespaceURI);
att = xdCacheDefinition.CreateAttribute("v");
att.Value = "Group C";
item.Attributes.Append(att);
sharedItems.AppendChild(item);
break;
}
count++;
}
//Now go back to the main pivot table xml and add the cross references to complete filtering
var xdPivotTable = pivotTable.PivotTableXml;
var xdPivotFields = xdPivotTable.FirstChild["pivotFields"];
if (xdPivotFields == null)
return;
count = 0;
foreach (XmlElement pField in xdPivotFields)
{
//Find the asset type field
if (count == assetfieldidx)
{
var att = xdPivotTable.CreateAttribute("multipleItemSelectionAllowed");
att.Value = "1";
pField.Attributes.Append(att);
var items = pField.GetElementsByTagName("items")[0] as XmlElement;
items.RemoveAll();
att = xdPivotTable.CreateAttribute("count");
att.Value = "4";
items.Attributes.Append(att);
pField.AppendChild(items);
//Add the classes to the fields item collection
for (var i = 0; i < 3; i++)
{
var item = xdPivotTable.CreateElement("item", items.NamespaceURI);
att = xdPivotTable.CreateAttribute("x");
att.Value = i.ToString(CultureInfo.InvariantCulture);
item.Attributes.Append(att);
//Turn of the Cash class in the fielder
if (i == 1)
{
att = xdPivotTable.CreateAttribute("h");
att.Value = "1";
item.Attributes.Append(att);
}
items.AppendChild(item);
}
//Add the default
var defaultitem = xdPivotTable.CreateElement("item", items.NamespaceURI);
att = xdPivotTable.CreateAttribute("t");
att.Value = "default";
defaultitem.Attributes.Append(att);
items.AppendChild(defaultitem);
break;
}
count++;
}
pck.Save();
Sorry for all the edit but I have been working on this for a little while when I stumbled on this question. I created an extension method just for applying a filter. Give it the field name (it assumes there is a header line contining the column names), the filters you want to apply, and the worksheet containing the data or it will just the Pivot Table worksheet if no data worksheet is passed in. It have done basic testing so you should QA:
public static bool FilterField(this ExcelPivotTable pivotTable, string pageFieldName, IEnumerable<object> filters, ExcelWorksheet dataWorksheet = null)
{
//set the worksheet
var ws = dataWorksheet ?? pivotTable.WorkSheet;
//Set the cache definitions and cache fields
var xdCacheDefinition = pivotTable.CacheDefinition.CacheDefinitionXml;
var xeCacheFields = xdCacheDefinition.FirstChild["cacheFields"];
if (xeCacheFields == null)
return false;
//Go the field list in the definitions, note the field idx and valuesfor
var count = 0;
var fieldIndex = -1;
List<object> fieldValues = null;
foreach (XmlElement cField in xeCacheFields)
{
var att = cField.Attributes["name"];
if (att != null && att.Value.Equals(pageFieldName, StringComparison.OrdinalIgnoreCase))
{
//store the field data
fieldIndex = count;
var dataddress = new ExcelAddress(pivotTable.CacheDefinition.SourceRange.Address);
var valueHeader = ws
.Cells[dataddress.Start.Row, dataddress.Start.Column, dataddress.Start.Row, dataddress.End.Column]
.FirstOrDefault(cell => cell.Value.ToString().Equals(pageFieldName, StringComparison.OrdinalIgnoreCase));
if (valueHeader == null)
return false;
//Get the range minus the header row
var valueObject = valueHeader.Offset(1, 0, dataddress.End.Row - dataddress.Start.Row, 1).Value;
var values = (object[,])valueObject;
fieldValues = values
.Cast<object>()
.Distinct()
.ToList();
//kick back if the types are mixed
if (fieldValues.FirstOrDefault(v => v is string) != null && fieldValues.FirstOrDefault(v => !(v is string)) != null)
throw new NotImplementedException("Filter function does not (yet) support mixed parameter types");
//fill in the shared items for the field
var sharedItems = cField.GetElementsByTagName("sharedItems")[0] as XmlElement;
if (sharedItems == null)
continue;
//Reset the collection attributes
sharedItems.RemoveAllAttributes();
//Handle numerics - assume all or nothing
var isNumeric = fieldValues.FirstOrDefault(v => v is string) == null;
if (isNumeric)
{
att = xdCacheDefinition.CreateAttribute("containsSemiMixedTypes");
att.Value = "0";
sharedItems.Attributes.Append(att);
att = xdCacheDefinition.CreateAttribute("containsString");
att.Value = "0";
sharedItems.Attributes.Append(att);
att = xdCacheDefinition.CreateAttribute("containsNumber");
att.Value = "1";
sharedItems.Attributes.Append(att);
att = xdCacheDefinition.CreateAttribute("containsInteger");
att.Value = fieldValues.Any(v => !(v is int || v is long)) ? "0" : "1";
sharedItems.Attributes.Append(att);
}
//add the count
att = xdCacheDefinition.CreateAttribute("count");
att.Value = fieldValues.Count.ToString(CultureInfo.InvariantCulture);
sharedItems.Attributes.Append(att);
//create and add the item
foreach (var fieldvalue in fieldValues)
{
var item = xdCacheDefinition.CreateElement(isNumeric ? "n" : "s", sharedItems.NamespaceURI);
att = xdCacheDefinition.CreateAttribute("v");
att.Value = fieldvalue.ToString();
item.Attributes.Append(att);
sharedItems.AppendChild(item);
}
break;
}
count++;
}
if (fieldIndex == -1 || fieldValues == null)
return false;
//Now go back to the main pivot table xml and add the cross references to complete filtering
var xdPivotTable = pivotTable.PivotTableXml;
var xdPivotFields = xdPivotTable.FirstChild["pivotFields"];
if (xdPivotFields == null)
return false;
var filtervalues = filters.ToList();
count = 0;
foreach (XmlElement pField in xdPivotFields)
{
//Find the asset type field
if (count == fieldIndex)
{
var att = xdPivotTable.CreateAttribute("multipleItemSelectionAllowed");
att.Value = "1";
pField.Attributes.Append(att);
var items = pField.GetElementsByTagName("items")[0] as XmlElement;
if (items == null)
return false;
items.RemoveAll();
att = xdPivotTable.CreateAttribute("count");
att.Value = (fieldValues.Count + 1).ToString(CultureInfo.InvariantCulture);
items.Attributes.Append(att);
pField.AppendChild(items);
//Add the classes to the fields item collection
for (var i = 0; i < fieldValues.Count; i++)
{
var item = xdPivotTable.CreateElement("item", items.NamespaceURI);
att = xdPivotTable.CreateAttribute("x");
att.Value = i.ToString(CultureInfo.InvariantCulture);
item.Attributes.Append(att);
if (filtervalues.Contains(fieldValues[i]))
{
att = xdPivotTable.CreateAttribute("h");
att.Value = "1";
item.Attributes.Append(att);
}
items.AppendChild(item);
}
//Add the default
var defaultitem = xdPivotTable.CreateElement("item", items.NamespaceURI);
att = xdPivotTable.CreateAttribute("t");
att.Value = "default";
defaultitem.Attributes.Append(att);
items.AppendChild(defaultitem);
break;
}
count++;
}
return true;
}
To use it in the above example, you would do something like this:
pivotTable.FilterField("Col2", new List<string> { "Group B" });

Categories