Skip to content

Commit a030f44

Browse files
committed
Uploaded sample
1 parent 7326de5 commit a030f44

17 files changed

+1357
-0
lines changed

App.config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<configuration>
3+
<startup>
4+
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
5+
</startup>
6+
</configuration>

Form1.Designer.cs

Lines changed: 158 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Form1.cs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.ComponentModel;
5+
using System.Data;
6+
using System.Drawing;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading.Tasks;
10+
using System.Windows.Forms;
11+
using System.Data.Entity;
12+
using System.IO;
13+
14+
namespace tx_sort_query
15+
{
16+
public partial class Form1 : Form
17+
{
18+
public Form1()
19+
{
20+
InitializeComponent();
21+
}
22+
23+
private string sDataSource = "data.xml";
24+
private string sTemplateFile = "template.tx";
25+
26+
private void mergeToolStripMenuItem_Click(object sender, EventArgs e)
27+
{
28+
// convert the XML file to a .NET DataSet
29+
DataSet ds = new DataSet();
30+
ds.ReadXml(sDataSource, XmlReadMode.Auto);
31+
32+
// create a new DataSelector instance
33+
DataSelector selector = new DataSelector(ds, File.ReadAllBytes(sTemplateFile));
34+
35+
// load the modified template
36+
mailMerge1.LoadTemplateFromMemory(selector.Template, TXTextControl.DocumentServer.FileFormat.InternalUnicodeFormat);
37+
// merge the template with the new, sorted data source
38+
mailMerge1.Merge(ds.Tables[0]);
39+
40+
// copy the merged document into a visible TextControl object
41+
byte[] data = null;
42+
mailMerge1.SaveDocumentToMemory(out data, TXTextControl.BinaryStreamType.InternalUnicodeFormat, null);
43+
textControl1.Load(data, TXTextControl.BinaryStreamType.InternalUnicodeFormat);
44+
}
45+
}
46+
47+
// DataSelector
48+
// description: This class loops through all merge blocks in a given template to check
49+
// for sort keywords. The given referenced DataSet will be sorted.
50+
//
51+
// Parameters: dataSet of type DataSet, template as a byte[] array in the InternalUnicodeFormat
52+
public class DataSelector
53+
{
54+
public byte[] Template { get; set; }
55+
56+
public DataSelector(DataSet dataSet, byte[] template)
57+
{
58+
// use a temporary ServerTextControl instance to recognize blocks with
59+
// the sorting keyword 'ORDERBY'
60+
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
61+
{
62+
tx.Create();
63+
// load the template
64+
tx.Load(template, TXTextControl.BinaryStreamType.InternalUnicodeFormat);
65+
66+
// create a list of merge blocks
67+
List<MergeBlock> lMergeBlocks = MergeBlock.GetMergeBlocks(MergeBlock.GetBlockMarkersOrdered(tx), tx);
68+
69+
// loop through all merge blocks to check whether they
70+
// have a sorting parameter
71+
foreach (MergeBlock mergeBlock in lMergeBlocks)
72+
{
73+
string sBlockName = mergeBlock.StartMarker.TargetName;
74+
75+
// check for the unique sorting parameter
76+
if (sBlockName.ToUpper().Contains("ORDERBY") == false)
77+
continue;
78+
79+
// create a new SortedBlock object to store parameter
80+
SortedBlock block = new SortedBlock(sBlockName);
81+
82+
// remove the sorting parameter from the block name
83+
// so that MailMerge can find the matching data in the data source
84+
mergeBlock.StartMarker.TargetName = block.Name;
85+
mergeBlock.EndMarker.TargetName = "BlockEnd_" + mergeBlock.Name;
86+
87+
if (dataSet.Tables.Contains(mergeBlock.Name) == false)
88+
continue;
89+
90+
// get all DataRows using LINQ
91+
var query = from product in dataSet.Tables[mergeBlock.Name].AsEnumerable()
92+
select product;
93+
94+
// create a new DataTable with the sorted DataRows
95+
DataTable dtBoundTable = (block.SortType == SortType.ASC) ?
96+
query.OrderBy(product => product.Field<String>(block.ColumnName)).CopyToDataTable() :
97+
query.OrderByDescending(product => product.Field<String>(block.ColumnName)).CopyToDataTable();
98+
99+
// remove original rows and replace with sorted rows
100+
dataSet.Tables[mergeBlock.Name].Rows.Clear();
101+
dataSet.Tables[mergeBlock.Name].Merge(dtBoundTable);
102+
103+
dtBoundTable.Dispose();
104+
}
105+
106+
// save the template
107+
byte[] data = null;
108+
tx.Save(out data, TXTextControl.BinaryStreamType.InternalUnicodeFormat);
109+
this.Template = data;
110+
}
111+
}
112+
}
113+
114+
// SortedBlock
115+
// description: this class is a container to store the block sorting parameters
116+
// the parameter string has the following format:
117+
//
118+
// [BLOCKNAME];orderby,[COLUMNNAME],DESC|ASC
119+
public class SortedBlock
120+
{
121+
public string Name { get; set; }
122+
public string ColumnName { get; set; }
123+
public SortType SortType { get; set; }
124+
125+
public SortedBlock(string SortedBlockName)
126+
{
127+
// the name of the block is the first part the semicolon separated string
128+
string[] saBlockValues = SortedBlockName.Split(';');
129+
this.Name = (string)saBlockValues.GetValue(0);
130+
131+
// the second part of separated by commas
132+
string[] saSortedBlockParameters =
133+
((string)saBlockValues.GetValue(1)).Split(',');
134+
this.ColumnName = saSortedBlockParameters[1];
135+
136+
this.SortType =
137+
(SortType)Enum.Parse(typeof(SortType),
138+
saSortedBlockParameters[2]);
139+
}
140+
}
141+
142+
public enum SortType
143+
{
144+
ASC = 0,
145+
DESC = 1
146+
}
147+
}

0 commit comments

Comments
 (0)