Programmatically populating html table cells - c#

I would like to loop through a table that I created using C# code and display data pulled from a Sharepoint list which was formatted in a table. This is the code I came up with:
protected override void RenderContents(HtmlTextWriter output)
{
try
{
SPSite thisSite = SPControl.GetContextSite(Context);
using (SPWeb topWeb = thisSite.OpenWeb("/"))
{
SPList newsList = topWeb.Lists["Headlines"];
SPQuery query = new SPQuery();
query.ExpandRecurrence = true;
query.Query = NewsListCamlQuery;
query.RowLimit = 2;
SPListItemCollection coll = newsList.GetItems(query);
output.Write("<table border='0' style='width: 100%;'><tbody>");
for (int i = 0; i < 2; i++)
{
output.Write("<tr>");
for (int j = 0; j < 3; j++)
{
output.Write("<td>");
foreach (SPListItem item in coll)
{
int newsID = int.Parse(item.ID.ToString());
output.Write("<hr/>");
output.Write("<table style='width: 100%; height: 143px;'><tbody>");
output.Write("<tr><td valign='top'><h4>");
output.Write(item["Title"].ToString());
output.Write("</h4></td></tr>");
output.Write("<tr><td valign='top'><h4 class='ms-rteElement-H4B'><span style='font-size: 8pt;'>");
output.Write(item["Sub_x0020_Heading"].ToString());
output.Write("</span></h4></td></tr>");
output.Write("<tr><td valign='top'><span style='font-size: 8pt;'>");
output.Write("<img class='image' src='");
//output.Write(item["Photo"].ToString());
output.Write("' Width='64px' Height='48px' Border='0' alt='' style='margin: 5px;'/>");
output.Write(item["Details"].ToString());
output.Write("</span></td></tr>");
output.Write("<tr><td valign='top'>");
output.Write("<a class='mt-linkMore' href='/Lists/Headlines/DispForm.aspx?ID=");
output.Write(newsID);
output.Write("' <span style='font-size: 6pt;'>Read More</span></a></td></tr>");
output.Write("</tbody></table>");
}
output.Write("</td>");
}
output.Write("</tr>");
}
output.Write("</tbody></table>");
}
}
catch (Exception exception)
{
output.Write("Error : " + exception.Message);
}
}
This code is currently re-writing the same record in each cell. I would like for it to display the six records that is being pulled from the Sharepoint list.

if you want to display two lines of 3 cells, you should not put the foreach.
On the inside of the second loop, you can make reference directly to the element of your list:
for (int i = 0; i < 2; i++)
{
output.Write("<tr>");
for (int j = 0; j < 3; j++)
{
output.Write("<td>");
int index;
if (i = 0)
index = j;
else
index = j + 3;
SPListItem item = coll[index];
int newsID = int.Parse(item.ID.ToString());
...

Related

I want to display one item per column in a table with a c# splitstring

I display the data coming from an excel table and I separate them with a splitstring and I want each item to be displayed in cells separated horizontally rather than separated vertically
here is my code to display the data :
private void btnExcelReader_Click(object sender, EventArgs e)
{
long lastRow = excelRange.Rows.Count;
long lastCol = excelRange.Columns.Count;
int rowTotal = 0;
for (int i = 1; i < lastRow; i++)
{
if (excelRange.Cells[i, 1].Value2 != null)
{
rowTotal++;
}
}
for (int i = 1; i < rowTotal; i += 4)
{
char[] separator = new char[] { ' ' };
string current = excelRange.Cells[i, 1].Value2;
string[] splitCurrent = current.Split(separator,
StringSplitOptions.RemoveEmptyEntries);
for (int j = 0; j < splitCurrent.Length; j++)
{
lvName.Items.Add(splitCurrent[j]);
}
}
lvName.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
lvName.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}
I try with columns.add, i create list and after that put my item in subitems.. nothing work.
Here is the image of the result in my ListView :

Populate datagridview from database

I am trying to fill datagridview from database (cassandra), but for some reason it shows only one row instead of two, can you tell me what I am doing wrong.
public void show_db()
{
var cluster = Cluster.Builder().AddContactPoint("127.0.0.1").Build();
var session = cluster.Connect("hotel");
RowSet rs = session.Execute("SELECT * FROM hotel.staff");
foreach (var res in rs)
{
for (int i = 0; 2 < 3; i++)
{
for (int j = 0; j < 4; j++)
{
staff_info.Rows[i].Cells[j].Value = res.GetValue<string>("staff_id");
staff_info.Rows[i].Cells[j].Value = res.GetValue<string>("username");
staff_info.Rows[i].Cells[j].Value = res.GetValue<string>("password");
staff_info.Rows[i].Cells[j].Value = res.GetValue<string>("name");
}
}
}
}
It's from database
This is from the application

Using CSS how to have row of tables followed by row of tables

I have an Array of Tables. For example 6 x 6. and a PlaceHolder.
I need to place the tables 6 next to each other in the PlaceHolder and then a new line of 6 next to each other, etc. What css properties do I add for each grid to achieve this.
I have
LiteralControl ltr = new LiteralControl();
ltr.Text = "<style type=\"text/css\" rel=\"stylesheet\">" + #".fl { float: left}</style>";
this.Page.Header.Controls.Add(ltr);
Table[,] tableArray = new Table[6,6];
for (int j = 0; j < tableArray.GetLength(0); j++)
{
bool first = true;
for (int i = 0; i < tableArray.GetLength(1); i++)
{
if (first)
{
tableArray[j, i].CssClass = "mGrid";
first = false;
}
else
{
tableArray[j, i].CssClass = "fl mGrid";
}
tableArray[j, i].Width = Unit.Percentage(100 / 6);
PlaceHolderTables.Controls.Add(tableArray[j, i]);
}
}
But I do not know how to start a new row and then have 5 next to it etc. I am inexperienced with CSS. The tables has been initialised else where. mGrid is defined elsewhere as well.
You can place those 36 tables inside a table with 6x6.
protected void Page_Load(object sender, EventArgs e)
{
LiteralControl ltr = new LiteralControl();
ltr.Text = "<style type=\"text/css\" rel=\"stylesheet\">" + #".fl { float: left}</style>";
Page.Header.Controls.Add(ltr);
Table main = new Table();
for (int i = 0; i < 6; i++)
{
TableRow row = new TableRow();
for (int j = 0; j < 6; j++)
{
Table table = CreateTable($"{i}x{j}");
TableCell cell = new TableCell();
cell.Controls.Add(table);
row.Controls.Add(cell);
}
main.Controls.Add(row);
}
PlaceHolderTables.Controls.Add(main);
}
private Table CreateTable(string text)
{
TableCell cell = new TableCell();
cell.Controls.Add(new Literal {Text = text });
TableRow row = new TableRow();
row.Cells.Add(cell);
Table table = new Table();
table.Rows.Add(row);
return table;
}

remove the row using NPOI Excel tool c#

I want to extract some data in the datatable, and want to send the email.
But when I extract the data, excel has many blanks between the extracted data.
The data which is not extracted make a blank row.
When I try to use RemoveRow() function, it doesn't work and still has a blank row.
private void Email()
{
//get the data from database
DataTable data = GetData();
int maxLavel = Convert.ToInt32(data.Compute("max([AssignedID])", string.Empty));
IWorkbook workbook;
workbook = new HSSFWorkbook();
for (int Emp = 0; Emp < maxLavel; Emp++)
{
ISheet sheet1 = workbook.CreateSheet("Sheet 1");
int num = 0;
//make a header row
IRow row1 = sheet1.CreateRow(0);
for (int j = 0; j < data.Columns.Count; j++)
{
ICell cell = row1.CreateCell(j);
String columnName = data.Columns[j].ToString();
cell.SetCellValue(columnName);
}
//loops through data
for (int i = 0; i < data.Rows.Count; i++)
{
IRow row = sheet1.CreateRow(i + 1);
if (Emp == Convert.ToInt32(data.Rows[i][0]))
{
num++;
ICell cell = row.CreateCell(j);
for (int j = 0; j < data.Columns.Count; j++)
{
sheet1.AutoSizeColumn(j); //control cell width
String columnName = data.Columns[j].ToString();
cell.SetCellValue(data.Rows[i][columnName].ToString());
}
}
else ///here has problems
{
var row = sheet1.GetRow(i);
//sheet1.RemoveRow(row);
sheet1.ShiftRows(i + 1, sheet1.LastRowNum + 1, -1);
}
}
if (num != 0)
{
//send email
}
}
}
I'm not sure why you need to resend the same file again with different contents instead of simply sending a different file, but could you perhaps try moving the creation of your sheet inside the for loop, and try removing the entire sheet instead? E.g. something like this:
private void Email()
{
//get the data from database
DataTable data = GetData();
int maxLavel = Convert.ToInt32(data.Compute("max([AssignedID])", string.Empty));
IWorkbook workbook;
workbook = new HSSFWorkbook();
for (int Emp = 0; Emp < maxLavel; Emp++)
{
ISheet sheet1 = workbook.CreateSheet("Sheet 1");
int num = 0;
//make a header row
IRow row1 = sheet1.CreateRow(0);
for (int j = 0; j < data.Columns.Count; j++)
{
ICell cell = row1.CreateCell(j);
String columnName = data.Columns[j].ToString();
cell.SetCellValue(columnName);
}
//loops through data
for (int i = 0; i < data.Rows.Count; i++)
{
IRow row = sheet1.CreateRow(i + 1);
if (Emp == Convert.ToInt32(data.Rows[i][0]))
{
num++;
for (int j = 0; j < data.Columns.Count; j++)
{
ICell cell = row.CreateCell(j);
sheet1.AutoSizeColumn(j); //control cell width
String columnName = data.Columns[j].ToString();
cell.SetCellValue(data.Rows[i][columnName].ToString());
}
}
}
if (num != 0)
{
//send email
}
workbook.remove(sheet1);
}
}
I figure it out..I don't need to remove the row.
IRow row = sheet1.CreateRow(i);
This should be changed.
for (int i = 0; i < data.Rows.Count; i++)
{
if (Emp == Convert.ToInt32(data.Rows[i][0]))
{
IRow row = sheet1.CreateRow(row_num);
num++; row_num++;
for (int j = 0; j < data.Columns.Count; j++)
{
ICell cell = row.CreateCell(j);
sheet1.AutoSizeColumn(j); //control cell width
String columnName = data.Columns[j].ToString();
cell.SetCellValue(data.Rows[i][columnName].ToString());
}
}
}

DataGridView: Copy complete to clipboard

I have a DataGridView in a .Net application (V4 C# VS2010) & want to copy all the data to the clipboard on the click of a button. No problem -
private void copyToClipboard()
{
dataGridView1.SelectAll();
DataObject dataObj = dataGridView1.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}
Problem is that the user might already have some cells, rows etc selected on the DataGrid & I don't really want to change that selection. The above obviously selects everything. I could dataGridView1.ClearSelection(); at the end which is marginally better but still doesn't achieve what's required.
I can save the selected cells:
var mySelectedCells = dataGridView1.SelectedCells;
but how do I get those selected cells reselected on the DataGrid after the copy? Is there an easy way to get the selected cells collection back into the DataGrid? Perhaps there is a better way to get the whole grid copied to the clipboard in the first place without affecting presently selected cells?
I suppose if you just wanted to represent the contents of the cells as text and copy them to the clipboard, tab-delimited, you could do something like:
var newline = System.Environment.NewLine;
var tab = "\t";
var clipboard_string = "";
foreach (DataGridViewRow row in dataGridView1.Rows)
{
for (int i=0; i < row.Cells.Count; i++)
{
if(i == (row.Cells.Count - 1))
clipboard_string += row.Cells[i].Value + newline;
else
clipboard_string += row.Cells[i].Value + tab;
}
}
Clipboard.SetText(clipboard_string);
The output seems pretty similar to that of the GetClipboardContent(), but be careful for any DataGridViewImageColumns or any type that isn't implicitly a string.
Edit: Anthony is correct, use StringBuilder to avoid allocating a new string for every concatenation. The new code:
var newline = System.Environment.NewLine;
var tab = "\t";
var clipboard_string = new StringBuilder();
foreach (DataGridViewRow row in dataGridView1.Rows)
{
for (int i = 0; i < row.Cells.Count; i++)
{
if (i == (row.Cells.Count - 1))
clipboard_string.Append(row.Cells[i].Value + newline);
else
clipboard_string.Append(row.Cells[i].Value + tab);
}
}
Clipboard.SetText(clipboard_string.ToString());
Here is a version of the VB code in C# with options to copy headers and to only copy selected rows.
private void CopyDataGridViewToClipboard(DataGridView dgv, bool includeHeaders = true, bool allRows = false)
{
// copies the contents of selected/all rows in a data grid view control to clipboard with optional headers
try
{
string s = "";
DataGridViewColumn oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
if (includeHeaders)
{
do
{
s = s + oCurrentCol.HeaderText + "\t";
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
}
while (oCurrentCol != null);
s = s.Substring(0, s.Length - 1);
s = s + Environment.NewLine; //Get rows
}
foreach (DataGridViewRow row in dgv.Rows)
{
oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible);
if (row.Selected || allRows)
{
do
{
if (row.Cells[oCurrentCol.Index].Value != null) s = s + row.Cells[oCurrentCol.Index].Value.ToString();
s = s + "\t";
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, DataGridViewElementStates.Visible, DataGridViewElementStates.None);
}
while (oCurrentCol != null);
s = s.Substring(0, s.Length - 1);
s = s + Environment.NewLine;
}
}
Clipboard.SetText(s);
}
catch (Exception ex)
{
toolStripStatusLabel2.Text = #"Error: " + ex.Message;
}
}
You might want to include the column headers:
private void copyAllToClipboard()
{
var newline = System.Environment.NewLine;
var tab = "\t";
var clipboard_string = new StringBuilder();
int i;
for (i = 0; i < this.Columns.Count - 1; i++)
{
clipboard_string.Append(this.Columns[i].Name);
clipboard_string.Append(tab);
}
clipboard_string.Append(this.Columns[i].Name);
clipboard_string.Append(newline);
foreach (DataGridViewRow row in this.Rows)
{
for ( i = 0; i < row.Cells.Count - 1; i++)
{
clipboard_string.Append(row.Cells[i].Value);
clipboard_string.Append(tab);
}
clipboard_string.Append(row.Cells[i].Value);
clipboard_string.Append(newline);
}
Clipboard.SetText(clipboard_string.ToString());
}
I think below method will exactly do what you want. Just call this method with the DataGridView name at the button click event.
Private Sub CopyDataGridViewToClipboard(ByRef dgv As DataGridView)
Try
Dim s As String = ""
Dim oCurrentCol As DataGridViewColumn 'Get header
oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible)
Do
s &= oCurrentCol.HeaderText & Chr(Keys.Tab)
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, _
DataGridViewElementStates.Visible, DataGridViewElementStates.None)
Loop Until oCurrentCol Is Nothing
s = s.Substring(0, s.Length - 1)
s &= Environment.NewLine 'Get rows
For Each row As DataGridViewRow In dgv.Rows
oCurrentCol = dgv.Columns.GetFirstColumn(DataGridViewElementStates.Visible)
Do
If row.Cells(oCurrentCol.Index).Value IsNot Nothing Then
s &= row.Cells(oCurrentCol.Index).Value.ToString
End If
s &= Chr(Keys.Tab)
oCurrentCol = dgv.Columns.GetNextColumn(oCurrentCol, _
DataGridViewElementStates.Visible, DataGridViewElementStates.None)
Loop Until oCurrentCol Is Nothing
s = s.Substring(0, s.Length - 1)
s &= Environment.NewLine
Next 'Put to clipboard
Dim o As New DataObject
o.SetText(s)
Clipboard.SetDataObject(o, True)
Catch ex As Exception
ShowError(ex, Me)
End Try
End Sub
DataGridView columns can be visible/invisible and also can be displayed in different order then the order they were created. This code takes care of both:
public static void CopyGridViewToClipboard(DataGridView gvCopy)
{
if (gvCopy == null) return;
StringBuilder s = new StringBuilder();
int offset = gvCopy.ColumnHeadersVisible ? 1 : 0;
int visibleColumnsCount = 0;
//count visible columns and build mapping between each column and it's display position
Dictionary<int, int> indexMapping = new Dictionary<int, int>();
int currIndex = 0;
int lastFoundMinDisplayIndex = -1;
for (int j = 0; j < gvCopy.ColumnCount; j++)
{
//find min DisplayIndex >= currIndex where column is visible
int minDisplayIndex = 100000;
int minDisplayIndexColumn = 100000;
for (int k = 0; k < gvCopy.ColumnCount; k++)
{
if ((gvCopy.Columns[k].Visible) && (gvCopy.Columns[k].DisplayIndex >= currIndex) && (gvCopy.Columns[k].DisplayIndex > lastFoundMinDisplayIndex))
{
if (gvCopy.Columns[k].DisplayIndex < minDisplayIndex)
{
minDisplayIndex = gvCopy.Columns[k].DisplayIndex;
minDisplayIndexColumn = k;
}
}
}
if (minDisplayIndex == 100000) break;
indexMapping.Add(minDisplayIndexColumn, currIndex);
lastFoundMinDisplayIndex = minDisplayIndex;
currIndex++;
}
visibleColumnsCount = currIndex;
//put data in temp array -- required to position columns in display order
string[,] data = new string[gvCopy.RowCount + offset, visibleColumnsCount];
if (gvCopy.ColumnHeadersVisible)
{
for (int j = 0; j < gvCopy.ColumnCount; j++)
{
if (gvCopy.Columns[j].Visible)
{
data[0, indexMapping[j]] = gvCopy.Columns[j].HeaderText;
}
}
}
for (int i = 0; i < gvCopy.RowCount; i++)
{
for (int j = 0; j < gvCopy.ColumnCount; j++)
{
if (gvCopy.Columns[j].Visible)
{
data[i + offset, indexMapping[j]] = gvCopy[j, i].FormattedValue.ToString();
}
}
}
//copy data
for (int i = 0; i < gvCopy.RowCount + offset; i++)
{
for (int j = 0; j < visibleColumnsCount; j++)
{
s.Append(data[i, j]);
s.Append("\t");
}
s.Append("\r\n");
}
Clipboard.SetDataObject(s.ToString());
}
You should change multiselect property of DataGridView. Here is the code:
private void copyToClipboard()
{
dataGridView1.MultiSelect = True;
dataGridView1.SelectAll();
DataObject dataObj = dataGridView1.GetClipboardContent();
if (dataObj != null)
Clipboard.SetDataObject(dataObj);
}

Categories

Resources