I will be the first to admit that the DevExpress controls have a lot of properties, a lot of designers, and there is a lot to learn. To say that the DevExpress controls are feature rich in short is am understatement. I know this because I work every day trying to learn them all. I work on learning them, acquiring knowledge of them as extemporaneous knowledge so that when I run into customers at conferences I can offer assistance in a timely manner. This also explains why more frequently I see want ads that ask for Developer Express experience specifically. (For example, I just got an email from Domino in Ann Arbor; Dominos is look for just such a candidate. Contact Todd Bohlen at todd.bohlen@dominos.com if you are interested.)
I don’t mean to say that using our controls is hard. for the most part the default settings will get you up and running without a lot of tweaking, and the LookAndFeel feature will help you get a professional looking skin with one property setting. However, if you want to be an expert then you have some work ahead of you. To help DevExpress is cranking out new features all the time and to keep our customers going we are cranking out videos, blogs, tweets, and attending conferences all the time too. The way this works is the product group evangelists imagineer something or we get a custom query and write a blog in conjunction with the support answer to make sure the information gets as broad an audience as possible. Of course, we encourage our customers to post queries to support to help us make the products better, but I also tell people at conferences if you need help feel free to contact me directly. In response to a customer query one of our developers suggest I explore some of the features of exporting data to Excel from an XtraPivotGrid, and they had an example already to go.
MS-Excel is widely used by office workers and developers at the behest of customers. I know this because I wrote a revised edition of Excel 2003 VBA Programmer’s Reference in 2003 and it is still selling several hundred copies every quarter.
The example forwarded to me demonstrates hwo to manually create some data, but any data will do. The example also shows how to programmatically set a bunch of properties to tweak the WYSIWYG view of the data in Excel. For blogs screen shots are good and code works well because you can read the code, copy it, or download it. (For videos, I generally prefer to use designers because they play better in a video format.)
The customer query in question asked about getting rid of some of the header data for the Excel export, so that is included in the code sample. The data is just some make believe data, but collectively the code gives you an idea of just a few of the property-features that are available. When you see a property chain like pivotGridControl1.OptionsPrint.PrintFilterHeaders what you are seeing are nested properties. In this instance it means that you should look in the PivotGridControl property list for OptionsPrint, expand that and find PrintFilterHeaders. In feature rich controls like ours there are going to a lot of nested properties; this is done to help organize by property groups.
Listing 1 contains the code sample that produces the basic WinFoms GUI shown in Figure 1, and when the data is exported the results will look like Figure 2. An overview of the code is provided after Listing 1.
Figure 1: The GUI with the data added by the PopulateTable method.
Figure 2: The data output to MS Excel; notice that the selected cell A1 (or that general area) doesn’t include the data fields represented by the ellipses in Figure 1.
The design time view has an XtraPivotGrid, a button, and a DataSet on it. Follow these steps to create the DataSet’s DataTable structure.
- Select the DataSet and display the Properties window
- Open the DataSet’s Tables Collection Editor—see Figure 3
- Click Add to add a DataTable
- Change the TableName property to Data
- Click on the Table’s Column property to open the Columns Collection Editor—see Figure 4
- Click the Add button to Add three members, naming them Name, Date, Value, respectively
- Change Name’s DataType to System.String
- Change Date’s DataType to System.DateTime
- Change Value’s DataType to System.Decimal
- Close the Column’s Collection Editor
- Close the Tables Collection Editor
- Assign DataSet1 to the PivotGridControl’s DataSource property
- Assign the Data table to the PivotGridControl’s DataMember property
Figure 3: Use the Tables Collection Editor to manually add tables to a DataSet.
Figure 4: Use the Columns Collection Editor to manually add columns to a DataTable.
After completing steps 1 through 13 above right-click on the PivotGridControl and select Run designer. Using Figure 5 as a visual guide drag and drop the Dame field once, the Date field twice, and the Value field three times to the PivotGrid Fields list. The field duplicates will be used for things like Sum, Count, and Average.
Figure 5: Add three more PivotGrid fields using the Add button.
Follow these steps to configure each of the fields:
- Set fieldName Area property to RowArea
- Set the fieldDate Area to ColumnArea and change the Caption to Year and the GroupInterval property to DateYear
- Set the fieldValue Area to DataArea, Caption to Sum
- Set fieldValue1 Area to DataArea, Caption to Count, and SummaryType to Count
- Set fieldValue2 Area to DataArea, Caption to Average, and SummaryType to Average
- Set fieldDate1 Area to ColumnArea, Caption to Date
- Close the designer
The design time view should look like Figure 6. The code is provided in Listing 1. (It is worth noting that if you use an actual datasource, say from a database, a lot of these steps are performed for you. It is also worth nothing that you can drag and drop fields at design time and runtime rather than changing the Area property of each field.)
Figure 6: The design time view after adding additional fields to the PivotGridControl.
Listing 1: The code-behind that adds data and performs the export to Excel operation.
using System;
usingSystem.Collections.Generic;
usingSystem.ComponentModel;
usingSystem.Data;
usingSystem.Drawing;
usingSystem.Text;
usingSystem.Windows.Forms;
usingDevExpress.XtraPrinting;
usingDevExpress.XtraPivotGrid;
namespaceWindowsApplication53
{
public partial classForm1: Form
{
publicForm1()
{
InitializeComponent();
}
private voidForm1_Load(objectsender, EventArgs e)
{
PopulateTable();
pivotGridControl1.RefreshData();
pivotGridControl1.BestFit();
}
private voidPopulateTable()
{
DataTable myTable = dataSet1.Tables["Data"];
myTable.Rows.Add(new object[] {"Aaa", DateTime.Today, 7});
myTable.Rows.Add(new object[] { "Aaa", DateTime.Today.AddDays(1), 4 });
myTable.Rows.Add(new object[] { "Bbb", DateTime.Today, 12 });
myTable.Rows.Add(new object[] { "Bbb", DateTime.Today.AddDays(1), 14 });
myTable.Rows.Add(new object[] { "Ccc", DateTime.Today, 11 });
myTable.Rows.Add(new object[] { "Ccc", DateTime.Today.AddDays(1), 10 });
myTable.Rows.Add(new object[] { "Aaa", DateTime.Today.AddYears(1), 4 });
myTable.Rows.Add(new object[] { "Aaa", DateTime.Today.AddYears(1).AddDays(1), 2 });
myTable.Rows.Add(new object[] { "Bbb", DateTime.Today.AddYears(1), 3 });
myTable.Rows.Add(new object[] { "Bbb", DateTime.Today.AddDays(1).AddYears(1), 1 });
myTable.Rows.Add(new object[] { "Ccc", DateTime.Today.AddYears(1), 8 });
myTable.Rows.Add(new object[] { "Ccc", DateTime.Today.AddDays(1).AddYears(1), 22 });
}
stringfileName = "pivot.xls";
private voidbutton1_Click(objectsender, EventArgs e)
{
pivotGridControl1.BeginUpdate();
pivotGridControl1.OptionsPrint.PrintColumnHeaders =
DevExpress.Utils.DefaultBoolean.False;
pivotGridControl1.OptionsPrint.PrintDataHeaders =
DevExpress.Utils.DefaultBoolean.False;
pivotGridControl1.OptionsPrint.PrintFilterHeaders =
DevExpress.Utils.DefaultBoolean.False;
PivotGridField fieldExportHeader = pivotGridControl1.Fields.Add();
fieldExportHeader.Caption = "Export";
fieldExportHeader.Name = "fieldExportHeader";
fieldExportHeader.Area = DevExpress.XtraPivotGrid.PivotArea.ColumnArea;
fieldExportHeader.Visible = true;
fieldExportHeader.AreaIndex = 0;
fieldExportHeader.TotalsVisibility = PivotTotalsVisibility.None;
pivotGridControl1.OptionsView.ShowGrandTotalsForSingleValues = true;
pivotGridControl1.EndUpdate();
try
{
pivotGridControl1.ExportToXls(fileName);
System.Diagnostics.Process.Start(fileName);
}
catch(System.Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
pivotGridControl1.Fields.Remove(fieldExportHeader);
}
}
private voidpivotGridControl1_CustomExportFieldValue(objectsender,
DevExpress.XtraPivotGrid.CustomExportFieldValueEventArgs e)
{
TextBrick brick = e.Brick as TextBrick;
if(e.Brick == null) return;
if(e.Field != null&& e.Field.Name == "fieldExportHeader"
&& e.ValueType == PivotGridValueType.Value )
{
brick.Text = GetLayoutDiscription(sender as PivotGridControl, e.Field );
}
}
private voidpivotGridControl1_FieldValueDisplayText(objectsender,
PivotFieldDisplayTextEventArgs e)
{
if(e.Field != null&& e.Field.Name == "fieldExportHeader"
&& e.ValueType == PivotGridValueType.Value)
e.DisplayText = "Export in progress, please wait...";
}
private stringGetLayoutDiscription(PivotGridControl pivot,
PivotGridField unnecessaryField)
{
string text = "ColumnFields: ";
List<PivotGridField> fields = pivot.GetFieldsByArea(PivotArea.ColumnArea);
for(int i = 0; i < fields.Count ; i++)
{
if(object.ReferenceEquals(fields[i], unnecessaryField)) continue;
text = text + fields[i].ToString();
if(i < fields.Count - 1)
text = text + " -> ";
}
return text;
}
}
}
Tip: In Visual Studio select the PivotGridControl and use the Events view to add a CustomExportFieldValue and FieldValueDisplayText events for the PivotGridControl.
Form_Load calls PopulateTable that gives you some data to work with. If you use a database table then you will likely skip this step. pivotGridControl1.RefreshData does just what it says—you added data now we need to refresh the grid. The BestFit method automatically adjusts field columns to the minimum width needed to display the contents of each field.
PopulateTable simply adds some rows of data to the DataTable defined in the designer.
button1_Click contains the export code. BeginUpdate prevents the grid from updating while a bunch of changes are made. Call EndUpdate when all tweaks are made. The OptionsPrint features are set to hide the PrintColumnHeaders, PrintDataHeaders, and PrintFilterHeaders. A new PivotGridField is added to the ColumnArea with the caption “Export”, and the OptionsView.ShowGrandTotals property—to show the grand totals for the data fields—is set to true. ExportToXls actually exports the data to an MS-Excel file, and System.Diagnostics.Process.Start with a filename uses the operating system’s knowledge of file types to figure out which process to start, in this case MS-Excel due to the .xls extension. (You can use Automation to control Excel directly, but this approach isn’t necessary.) Finally, after the export the new PivotGridField is removed.
When the ExportToXls method is called CustomExportFieldValue is called for the PivotGridField added by the code. This event handler calls GetLayoutDescription which performs a tweak on the added field’s display text. FieldValueDisplayText displays an “exporting” message on the grid during the export.
There is a lot of tweaks going on with this code. Extra PivotGridFields are added and removed. Redundant field headers are hidden. (These are the dragable buttons the user has access to on the forms—to move fields between data, row, and column areas—that aren’t really needed in an Excel worksheet.) And, some tweaking of the text output is done.