We're sorry Aspose doesn't work properply without JavaScript enabled.

Free Support Forum - aspose.com

Question on Table merge

I have a table of data that contains 2 columns. These are year and amount. The requirement we have is to show this table of data in our word document.

I know this is real easy using TableStart and TableEnd functionality.

Howerver, part of the requirement is to show the records across 2 columns in a table.

For example, the data represents 4 years worth of earnings. What we would want is to show years 1 - 2 and earings for those years in the first 2 columns and show years 3 - 4 and the corresponding earnings amount in the next 2nd columns. Below is a rough example of what it would look like.

Year Earnings Year Amount
2010 $15,000 2008 $13,000
2009 $14,000 2007 $12,000

In reality this table will contain up to 30 years of data, but I think I made my point.

Is this even possible to do with Aspose using TableStart? I don't want to have to make individual mergefields for every single distinct value.

Hi

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Thank you for your interest in Aspose.Words. Sure, you can achieve this using mail merge with regions. You just need also use NEXT field. Your template should look like the following:

Year

Amount

Year

Amount

{ MERGEFIELD TableStart:myData }{ MERGEFIELD Year }

{ MERGEFIELD Amount }

{ NEXT }{ MERGEFIELD Year }

{ MERGEFIELD Amount }{ MERGEFIELD TableEnd:myData }

I attached simple template and output document produced by the following code:

// Create a dummy datasource.

DataTable data = new DataTable("myData");

data.Columns.Add("Year");

data.Columns.Add("Amount");

// Add some data

for (int i = 2000; i < 2011; i++)

data.Rows.Add(new object[] {i, "$1000"});

// Open template and execute mail merge with regions.

Document doc = new Document(@"Test001\in.doc");

doc.MailMerge.ExecuteWithRegions(data);

doc.MailMerge.DeleteFields();

doc.Save(@"Test001\out.doc");

Hope this helps.

Best regards.

The output isn't quite right. What they are wanting using your example should look like the attached document. Basically, it needs to run vertically for the 1st half and then the second 1/2 would be in the 2nd columns.

Thinking about it I don't think this can be done. Programatically it would have to know the total number of records and then be able to display the <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> record that is (current row + (total rows / 2)). Something similar to this:

Year

Amount

Year

Amount

{ MERGEFIELD TableStart:myData }{ MERGEFIELD Year }

{ MERGEFIELD Amount }

{ MOVE TO RECORD ROW (Current + (TotalRecords / 2) }{ MERGEFIELD Year }

{ MERGEFIELD Amount }{ MERGEFIELD TableEnd:myData }

I don't think you can skip to certain records so that would be a problem.

In case there are those that are interested, I created a workaround by manipulating DataTable default view sort. Basically, I added a dynamic column to my DataTable called SortKey. I then pass the DataTable.DefaultView to the ExecuteRegions call.

The magic occurs by setting the Sortkey based on a formula that uses 2 variables. The 1st is the number of records in the DataTable. The 2nd is the number of records to show per Word table row. Using this information, I can calculate a sortkey to use for each row based on a calculated offset. The code is something like:

// Logic to reset SortKeys based on # Cols

int NUMBER_COLS = 3;
int nRowCount = data.Rows.Count;
int nRemainder;

int Offset = Math.DivRem(nRowCount, NUMBER_COLS, out nRemainder);
if (nRemainder > 0) Offset++;

int nSortVal = 1;
for (int i = 0; i < Offset; i++)
{
for (int j = 0; j < NUMBER_COLS; j++)
{
int nRowNum = i + (Offset * j);
if (nRowNum < nRowCount) data.Rows[nRowNum]["SortKey"] = nSortVal++;
}
}

data.AcceptChanges();
data.DefaultView.Sort = "SortKey";

// Open template and execute mail merge with regions.
Document doc = new Document(Path.Combine(m_sOutputDirectory, "in.doc"));
doc.MailMerge.ExecuteWithRegions(data.DefaultView);
doc.MailMerge.DeleteFields();
doc.Save(Path.Combine(m_sOutputDirectory, "out.doc"));

Hi

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Thank you for additional information. It is perfect that you already found a solution. I would like to suggest you one more way to achieve the same (maybe simpler). You can just use section with two columns in your template. Please see the attached template and output document.

Hope this could help you.

Best regards.