separate datatable for each row in db. .NEt - c#

I have long tables generated by datagrid control that go beyond the page width. I would like to convert that into separate table for each row or definition list where each field name is followed by field value.
How would I do that.

Uses jquery. If you have more than one table you'll need to change it to accommodate that. Also, just appends to the end of the document. If you want it elsewhere, find the element you want to place it after and insert it into the DOM at that point.
$(document).ready(
function() {
var headers = $('tr:first').children();
$('tr:not(:first)').each(
function(i,row) {
var cols = jQuery(row).children();
var dl = jQuery('<dl></dl>');
for (var i=0, len = headers.length; i < len; ++i) {
var dt = jQuery('<dt>');
dt.text( jQuery(headers[i]).text() );
var dd = jQuery('<dd>');
dd.text( jQuery(cols[i]).text() );
dl.append(dt).append(dd);
}
$('body').append(dl);
}
);
$('table').remove();
}
);

Here's a reference:
http://www.mail-archive.com/flexcoders#yahoogroups.com/msg15534.html
The google terms I think you want are "invert datagrid". You'll get lots of hits.

Related

Reporting system on Aspose.Word / C#

I am currently in need of an idea, I'm developing a software solution and I have to create Words documents from BDD's information.
Everything is fine about informations's use but one point and it's the most important :
On my Word document, I use signets to repeat a table where information is written. One of the column refer to a cost, and since I'm using the signets's system, I don't know where my table end, it can take 1 page as it can take 2500's but I need to calculate at the end of EACH page a total of every row that was written on the current page, and then rewrite this total at the beginning of the next page. So it would be like :
Page 1
nameOfTheItem1 Cost1
nameOfTheItem2 Cost2
nameOfTheItem3 Cost3
nameOfTheItem4 Cost4
TOTAL PAGE 1 : TotalPage1
Page 2
TotalPage1
nameOfTheItem5 Cost5 nameOfTheItem6 Cost6 nameOfTheItem7
Cost7 nameOfTheItem8 Cost8 TOTAL PAGE 2 :
TotalPage2(+TotalPage1)
and this for each page existing for this document.
I'm still looking for a solution by myself, and every help would be great.
It can be done with the mail merge feature of Aspose.Words. The solution is particularly related to the nested mail merge.
You have to arrange the data in a DataSet, in order to make the report appear according to your requirements. For this scenario, arrange in 2 tables. One is "Page" and other is "Item"
Your template document (DOCX) should define the merge fields according the the image below. Note that there is a page break after the table.
The following code will help you to get started. It uses dummy data of course. You can populate with your own data to make it work for you.
MS Word template document that works with this code: Download Template
private void yourMethod()
{
string srcDoc = dataDir + "ItemsTemplate.docx";
string dstDoc = dataDir + "ItemsTemplate_Result.docx";
int totalRecords = 10;
int recordsPerPage = 4;
// Prepare some data
DataSet ds = getData(totalRecords, recordsPerPage);
// Prepare the document in Aspose
Aspose.Words.Document doc = new Aspose.Words.Document(srcDoc);
doc.MailMerge.ExecuteWithRegions(ds);
doc.MailMerge.CleanupOptions = Aspose.Words.Reporting.MailMergeCleanupOptions.RemoveEmptyParagraphs;
doc.Save(dstDoc);
Process.Start(dstDoc);
}
private DataSet getData(int totalRecords, int recordsPerPage)
{
DataSet ds = new DataSet("Dataset");
// Add the page table
System.Data.DataTable pageTable = new System.Data.DataTable("Page");
pageTable.Columns.Add("PageNumber");
pageTable.Columns.Add("PageTotal");
pageTable.Columns.Add("PreviousPageTotal");
// Add the item table
System.Data.DataTable itemTable = new System.Data.DataTable("Item");
itemTable.Columns.Add("ID");
itemTable.Columns.Add("Name");
itemTable.Columns.Add("Cost");
itemTable.Columns.Add("PageNumber");
// Add pages
int iRow = 1, iPage = 1;
while (iRow <= totalRecords )
{
DataRow pageRow = pageTable.NewRow();
pageRow["PageNumber"] = iPage;
pageRow["PageTotal"] = 0;
// Add the items in this page
int iRecordsPerPage = 1;
while (iRow <= totalRecords && iRecordsPerPage <= recordsPerPage)
{
DataRow itemRow = itemTable.NewRow();
itemRow["ID"] = iRow;
itemRow["Name"] = "Item " + iRow;
itemRow["Cost"] = iRow;
itemRow["PageNumber"] = iPage;
pageRow["PageTotal"] = int.Parse(pageRow["PageTotal"].ToString()) + int.Parse(itemRow["Cost"].ToString());
itemTable.Rows.Add(itemRow);
iRow++;
iRecordsPerPage++;
}
pageTable.Rows.Add(pageRow);
// Previous page total
if (iPage == 1)
pageRow["PreviousPageTotal"] = 0; // Always 0 for first page
else
pageRow["PreviousPageTotal"] = pageTable.Rows[iPage - 2]["PageTotal"]; // Get total of previous page
iPage++;
}
ds.Tables.Add(pageTable);
ds.Tables.Add(itemTable);
// We must have relationship for Aspose mail merge to work correctly
ds.Relations.Add(pageTable.Columns["PageNumber"], itemTable.Columns["PageNumber"]);
return ds;
}
Try changing the values of totalRecords and recordsPerPage variables and you will see the data arranged in pages accordingly. Just be sure to keep the recordsPerPage value low, so that it does not exceed single page.
I am a developer evangelist at Aspose.
I am exporting data to existing word template which is .dotx
But the final report does not show the table of contents even though i have added it in code.
My code is as follows
public void ExportToWordUsingTemplate()
{
Aspose.Words.Document doc1 = new Aspose.Words.Document(#"E:/excel/HOVEDMAL Prognoserapporter 2.dotx");
DocumentBuilder docBuilder1 = new DocumentBuilder(doc1);
SkinAPI.ReportAPISoapClient svc = new SkinAPI.ReportAPISoapClient();
SkinAPI.GetReportContextResult myReportContext = svc.GetReportContext(1);
docBuilder1.InsertHtml("<h1 align='left'>" + myReportContext[0].MainReportName + "</h1>");
docBuilder1.InsertTableOfContents("\\o \"1-3\" \\h \\z \\u");
//for (int i = 0; i < myReportContext.Count - 2; i++)
for (int i = 0; i < 5; i++)
{
SkinAPI.GetReportElementGraphDataResult myElementGraphData = svc.GetReportElementGraphData(myReportContext[i].ReportId, myReportContext[i].ElementId);
SkinAPI.GetReportElementDataResult myElementData = svc.GetReportElementData(myReportContext[i].ReportId, myReportContext[i].ElementId, 0, 0, 0); // Three last parameters set to 0, used when fetching drilldown data for tables that support it
docBuilder1.ParagraphFormat.StyleIdentifier = StyleIdentifier.Heading1;
docBuilder1.Writeln(myReportContext[i].ElementHeader);
docBuilder1.ParagraphFormat.StyleIdentifier = StyleIdentifier.BodyText;
// Is there a graph for this element, and has it a datasource other than the main data source as fetched above?
if (myReportContext[i].HasGraph && myReportContext[i].SeparateGraphDataSource)
{
// Is there a text part for this element
if (myReportContext[i].HasText)
{
// The returned string will contain a HTML text.
// Note that the text is connected to a TileId, not an ElementId, meening the text might have been fetched before.
string myElementHTMLDescription = svc.GetReportText(myReportContext[i].TileId);
docBuilder1.InsertHtml(myElementHTMLDescription);
}
}
docBuilder1.InsertBreak(BreakType.PageBreak);
}
doc1.Save(#"E:/excel/HOVEDMAL Prognoserapporter 2_Report.doc");
}

Using a foreach loop on LINQ query for searching

Hi I have a record called Tags in a table called Knowledgebase (KB) in my DB. The words in Tags are separated by commas. Also in the KB table is a field called Title.
I need to match the tags field to the Title so I have replaced all the commas in the tags with spaces like so string removeCommas = commas.Replace(",", " ");.
I think I now need to loop around every record in the KB table to find records? I would like to store the number of matches it finds in a variable called suggestions.
Question is what is the best way to implement the for each loop for a query like this? Is the for each loop the best method for this task?
One way is to store the space seperated strings in a List. Now, use Foreach loop for the whole table and in turn a foreach loop for each record to find the match of Title.
I will correct my answer if this is going the wrong direction, but would something like this complete the operation you are attempting?
System.Data.DataTable KB = new System.Data.DataTable();
string[] tags = "some,foo,bar".Split(',');
System.Collections.Generic.List<string> suggestions = new System.Collections.Generic.List<string>();
for (int i = 0; i < tags.Length; i++)
{
for (int j = 0; j < KB.Rows.Count; j++)
{
string row = KB.Rows[j]["Title"].ToString();
if ((row.Contains(tags[i]))
{
suggestions.Add(row);
}
}
}
Also, avoid foreach whenever humanly possible. Check out THIS post to see why.
Yes Linq can help you to retreive the data from your database and then replacing it after a foreach loop
Code Added
Let say you are using EDM and you have a context kb:
public void ReplaceCommaInTag(KbContext kb)
{
var tags = from t in kb.Titles
Select t.Tags;
foreach(Tag tag in tags)
{
tag = tag.Replace(","," ");
}
try
{
kb.SubmitChanges();
}
catch(Exception e)
{
//Display the error.
}
}
I hope it will help you

Get HTML Table ID in C# function?

In HTML page I've table with ID = "week1" and in C# function I'm using this as
week1.Rows.Add(TableCell);
I want to cast string in table ID. Suppose I've string
for(int i=0; i<5; i++)
{
String abc = "week" + i;
/*
How to do cast this string in table ID
like above to add rows and cell in table but above is hardcoded and I want
to make this dynamic.
*/
}
How to cast above string in HTML Table ID ?????
If your tables reside in a panel you can look them up like this. Please note that ofc you will need runat=server for them. I assume you use HtmlTable in your form ()
for (int i = 0; i < 5; i++)
{
var table = (HtmlTable)pnlTables.FindControl("week" + i);
if (table != null)
{
//do stuff with your table
}
}
Make sure your table in your .aspx has runat="server" (<table id="week1" runat="server">), then, in your code behind, you can simply do
week1.ID
or week1.ClientID (for the full ID in your DOM) - whichever one you're wanting.
Your table should have runat="server" attribute.Only then u can access it from code behind.

Removing a column by column name

I am working with the openxml sdk and have a table to write to a word doc. Once i have written my table, is there anyway to select all the columns for that table and delete one of them based on the text for that column? For example:
foreach (var column in table.columns)
{
if (column.Text == "Hello")
{
table[column].delete();
}
}
Is there a real world implementation of the above pseudo code?
Unfortunately, there is no concept of a "column" in a word processing table (DocumentFormat.OpenXml.WordProcessing.Table), only rows and cells. If you can assume the first row contains column names, and all rows contain the same number of cells, you can accomplish your task. One thing you have to be careful of (and one problem in your pseudocode above) is that you can't delete things from the enumeration you're currently iterating over. Here's how I would accomplish this:
var rows = table.Elements<TableRow>();
var firstRowCells = rows.ElementAt(0).Elements<TableCell>();
var cellNumbersToDelete = new List<int>();
for( int i=0; i<firstRowCells.Count(); i++ )
if( GetCellText( firstRowCells.ElementAt( i ) ) == "Hello" )
cellNumbersToDelete.Add( i );
foreach( var cellNumberToDelete in cellNumbersToDelete ) {
foreach( var row in rows ) {
cellToDelete = row.ElementAt( cellNumberToDelete );
row.RemoveChild( cellToDelete );
}
}
I don't have time right now to test this solution, so it'll probably require some tweaking, but it should give you a general idea about how to accomplish your task. The method GetCellText referenced above would look something like this:
string GetCellText( TableCell cell ) {
var p = cell.Elements<Paragraph>().First();
var r = p.Elements<Run>().First();
var t = r.Elements<Text>().First();
return t.Text;
}

In Telerik Radgrid, how can I page the results according the number of group headers?

Is there a way of set some "PageSize" property according the number of "Group Headers" in a RadGrid?
Regards!
The code snippet is bellow:
protected void PageResults(DataTable AnyDataTable) {
//Textbox where user inserts the number of registers that will be showed per page.
if (txt_register_per_page.Value.HasValue)
{
int RegistersPerPage = 0, EveryItens = 0;
string OldData = "";
//The loop runs over all the table's rows.
for (int Index = 0; Index <= AnyDataTable.Rows.Count; Index++)
{
//The "ColumName" is the one that all the others will be grouped.
//If no matches with the current data, means that is another "group".
if (!(String.Equals(AnyDataTable.Rows[Index]["ColumnName"].ToString(), OldData)))
{
RegistersPerPage++;
if (RegistersPerPage == txt_register_per_page.Value)
{
EveryItens = Index;
break;
}
OldData = AnyDataTable.Rows[Index]["ColumnName"].ToString();
}
}
MyRadGrid.PageSize = EveryItens;
}
}
As I see, the PageSize property allows the grid to show pages based in ALL the registers, then I tried to begin writing something that converts the total data for the respective number of groups that the user inputs on the textbox.
There is a pagesize property, but it doesn't take into affect the row type to do some specialized function. You'd have to examine the data (and do the grouping yourself) and manually calculate the groups... I don't know if that is an efficient solution.
What type of grouping calculation do you want to do?

Categories