Unable to format date in dataset column,GridView - asp.net

I am reading data from an excel sheet and displaying it in a data gridview.There are some date columns in the excel.So when i read the data from the excel and bind it to the dataGridView.The date is displayed in the format "02/02/2009 12:00:00 AM" but the actual data in the excel column is in the format "2/2/2009".So how to change the date format in the datagridview.
Since i am binding the data from the dataset i dont have any template columns or bound column set so i dont know where to set the HtmlEncode="False" DataFormatString = "{0:T}"
Is there any way to do this.Please help me.
Please find the below code sample.
string OleDbConnection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= "+ FileUpload1.PostedFile.FileName + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1\"";
string strSheetName = "Sheet1";
OleDbConnection oledbConnection;
OleDbCommand oledbCommand;
OleDbDataAdapter oledbAdapter;
oledbCommand = new OleDbCommand();
oledbAdapter = new OleDbDataAdapter();
DataSet dsExcellData = new DataSet();
oledbConnection = new OleDbConnection(OleDbConnection);
oledbConnection.Open();
oledbCommand.Connection = oledbConnection;
oledbCommand.CommandText = "Select * from [" + strSheetName + "$]"; // i want to find this sheet name
oledbAdapter.SelectCommand = oledbCommand;
oledbAdapter.Fill(dsExcellData);
oledbConnection.Close();
GridView1.DataSource = dsExcellData.Tables[0];
GridView1.DataBind();
==========================================================
I tried the
dsExcellData.Tables[0].Rows[rowcount]["date_column"].ToString()] = dsExcellData.Tables[0].Rows[rowcount]["date_column"].ToString()].ToString("d");
but the value is not getting assigned as "mm/dd/yyyy" It is also taking the time default time again (mm/dd/yyyy hh:mm:ss AM).
=============================================================
I am just assigning the data set to the gridview.The problem is the dataset is reading the date column in the format mm/dd/yyyy hh:mm:ss AM.I am unable to change the data in the dataset also.
=============================================================
Finaly i got the answer from ScottE:
we have to add the below code in the itemdatabound of the datagridview :
protected void dgValidatedData_ItemDataBound1(object sender, DataGridItemEventArgs e)
{
for (int i = 0; i <= e.Item.Cells.Count - 1; i++)
{
System.DateTime cellDate = default(System.DateTime);
if (System.DateTime.TryParse(e.Item.Cells[i].Text, out cellDate))
{
e.Item.Cells[i].Text = string.Format("{0:d}", cellDate);
}
}
}

Ok, try this, where "Item" is the column name (could be multiple) that is a date that needs formatting. This is of course vb.net, but you can sort that out. I'm sure there's a better way, but this works.
Protected Sub gv_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
For i As Integer = 0 To e.Row.Cells.Count - 1
If gv.HeaderRow.Cells(i).Text = "Item" Then
e.Row.Cells(i).Text = String.Format("{0:d}", CType(e.Row.Cells(i).Text, Date))
End If
Next
End If
End Sub
Or, if you don't know what columns will have dates, the following will work as well:
Protected Sub gv_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
For i As Integer = 0 To e.Row.Cells.Count - 1
Dim cellDate As Date
If Date.TryParse(e.Row.Cells(i).Text, cellDate) Then
e.Row.Cells(i).Text = String.Format("{0:d}", cellDate)
End If
Next
End If
End Sub

If you're binding it as a asp:BoundField you'll need to set htmlencode to false.
<asp:BoundField HtmlEncode="false" DataField="Blah" DataFormatString="{0:d}" />

Date format you should define in your GridView column. For example:
<asp:GridView>
...
<asp:TemplateField>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("Date", "{0:T}") %>'></asp:Label>
</ItemTemplate>
...
</asp:GridView>

Here is a solution using a custom control that derives from GridView:
using System;
using System.Collections;
using System.Web.UI.WebControls;
namespace CustomControls {
public class FormattedGridView : GridView {
protected override ICollection CreateColumns(PagedDataSource dataSource, bool useDataSource) {
// Call base method and return the collection as an ArrayList
var columns = (ArrayList) base.CreateColumns(dataSource, useDataSource);
for (var i = 0; i < columns.Count; i++) {
var agf = columns[i] as AutoGeneratedField;
if (agf != null && agf.DataType == typeof(DateTime)) {
// create a new column because the AutoGeneratedField does not support
// the modification of the DataFormatString property
var bf = new BoundField();
// copy some of the original properties
bf.DataField = agf.DataField;
bf.HeaderText = agf.HeaderText;
bf.HtmlEncode = false;
// set the format for the DateTime types
bf.DataFormatString = "{0:T}";
// replace the existing auto-generated colums
columns[i] = bf;
}
}
return columns;
}
}
}

Finaly i got the answer from ScottE:
we have to add the below code in the itemdatabound of the datagridview :
protected void dg_ItemDataBound1(object sender, DataGridItemEventArgs e)
{
for (int i = 0; i <= e.Item.Cells.Count - 1; i++)
{
System.DateTime cellDate = default(System.DateTime);
if (System.DateTime.TryParse(e.Item.Cells[i].Text, out cellDate))
{
e.Item.Cells[i].Text = string.Format("{0:d}", cellDate);
}
}
}
But the above code will check all the data that is bound to the datagrig.It will try to parse the data as datetime in the cell.If it is a valid datetime then it will convert the data into the format which we applied.

Related

gridview hide columns [duplicate]

This question already has answers here:
GridView Hide Column by code
(13 answers)
Closed 8 years ago.
I have gridview and I want to hide a column after databind to gridview but I get the error below.
"Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index"
My C# code is below,
protected void grid_all_posts_DataBound(object sender, EventArgs e)
{
if (grid_all_posts.Columns[1].Visible)
{
grid_all_posts.Columns[1].Visible = false;
}
}
// Read all posts and fill gridview
//////////////////////////////////////////////////
DbCommand dbCommand2;
dbCommand2 = db.GetStoredProcCommand("SP_Select_News");
db.AddInParameter(dbCommand2, "UserId", DbType.Guid, new Guid(Session["UserId"].ToString().Trim()));
DataSet ds = db.ExecuteDataSet(dbCommand2);
grid_all_posts.DataSource = ds;
grid_all_posts.DataBind();
//////////////////////////////////////////////////
My ASPX code,
<asp:gridview runat="server" ID="grid_all_posts" OnRowDataBound="grid_all_posts_DataBound"></asp:gridview>
What do you think the problem is? How I can hide the first column
Try like below it will work....
DbCommand dbCommand2;
dbCommand2 = db.GetStoredProcCommand("SP_Select_News");
db.AddInParameter(dbCommand2, "UserId", DbType.Guid, new Guid(Session["UserId"].ToString().Trim()));
DataSet ds = db.ExecuteDataSet(dbCommand2);
grid_all_posts.DataSource = ds;
grid_all_posts.DataBind();
**//after Databind Write the below code**
if (grid_all_posts.Columns.Count > 0)
grid_all_posts.Columns[0].Visible = false;
else
{
grid_all_posts.HeaderRow.Cells[0].Visible = false;
foreach (GridViewRow gvr in grid_all_posts.Rows)
{
gvr.Cells[0].Visible = false;
}
}
A simple and versatile approach for this has been bugging me for ages - something that does not require any kind of column counting, I eventually found it today; DataControlFieldCell.ContainingField.HeaderText
Private Sub GridView_RowDataBound(sender As Object, e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView.RowDataBound
For Each r As GridViewRow In GridView.Rows
If r.RowType = DataControlRowType.DataRow Then
For Each c As DataControlFieldCell In r.Cells
Dim h As String = c.ContainingField.HeaderText
If h <> "ColumnName" Then c.ContainingField.Visible = False
If IsNumeric(c.Text) Then c.Text = Format(CInt(c.Text), "#,##0")
Next
End If
Next
End Sub
I loop through the DataControlFieldCells as I perform some formatting on the values in my fields as well (as illustrated above) but you could just loop through the header I imagine if you wanted to cut it down further still.
See msdn for more details.

Count visitor of one page in asp.net

I have a page that contains a record of a database. I want to count number of visits of that page . I use codes below to counts number of visits of page by increment view field of record. but this increment view randomly. for example when I refresh page the view increment 20 !.
my codes for this page is:
protected void Page_Load(object sender, EventArgs e)
{
da db = new da();
string str = "select views from newstxt where id=" + Request.Params["id"].ToString();
DataTable dt = new DataTable();
dt = db.select(str);
int view = Int32.Parse(dt.Rows[0][0].ToString());
//increment
view++;
//
str = "update newstxt set views=N'{0}' where id=" + Request.Params["id"].ToString();
str = string.Format(str, view);
db.docom(str);
}
There are couple of ways for this approach
simple approach would be using a view state
declare a Property like
public int ViewCount
{
get { return (int)ViewState["viewcount"]; }
set { ViewState["viewcount"] = value; }
}
use like ViewCount++; on page load and to get value int value = ViewCount
i hope this helps !!!
Protected Sub Page_Load(sender As Object, e As EventArgs)
Me.countMe()
Dim tmpDs As New DataSet()
tmpDs.ReadXml(Server.MapPath("~/counter.xml"))
lblCounter.Text = tmpDs.Tables(0).Rows(0)("hits").ToString()
End Sub
Private Sub countMe()
Dim tmpDs As New DataSet()
tmpDs.ReadXml(Server.MapPath("~/counter.xml"))
Dim hits As Integer = Int32.Parse(tmpDs.Tables(0).Rows(0)("hits").ToString())
hits += 1
tmpDs.Tables(0).Rows(0)("hits") = hits.ToString()
tmpDs.WriteXml(Server.MapPath("~/counter.xml"))
End Sub
XML
<?xml version="1.0" encoding="utf-8" ?>
<counter>
<count>
<hits>0</hits>
</count>
Nothing seems to be wrong with your code but it seems like there is something wrong your Request.Params. Are you using query string, if it is then i would suggest you to use Request.QueryString instead. Also, what you want only if to update the count then you can avoid select query and reduce your code to:
da db = new da();
String str = "UPDATE newstxt SET views = views + 1 WHERE id=" + Request.QueryString["id"].Trim();
db.docom(str);

How to databind a repeater from stored procedure?

I'm trying to databind my repeater but so far not having any luck. Anyone think that can show me where I'm going wrong? I have two functions at the moment by following some tutorials/examples but I was hoping to have just one... maybe not possible. Thanks!
HTML:
<ItemTemplate>
<tr class="row">
<td><asp:Label ID="TitleLabel" runat="server" Text=""></asp:Label></td>
<td><asp:Label ID="NameLabel" runat="server" Text=""></asp:Label></td>
<td><asp:Label ID="PhoneLabel" runat="server" Text=""></asp:Label></td>
<td><asp:Label ID="EmailLabel" runat="server" Text=""></asp:Label></td>
</tr>
</ItemTemplate>
VB
Protected Sub BindData()
Dim oCommand As SqlCommand
Dim oReader As SqlDataReader
Try
oCommand = DataAccess.GetSQLCommand("People_Retrieve", CommandType.StoredProcedure, SourceServer.ConnectionLocal)
oCommand.Connection.ChangeDatabase("MyDatabase")
oCommand.CommandTimeout() = 9000
oReader = oCommand.ExecuteReader()
PeopleRepeater.DataSource = oReader
PeopleRepeater.DataBind()
Catch ex As Exception
ErrorHandler.HandleError(ex)
Finally
oReader.Close()
oReader = Nothing
End Try
End Sub
Protected Sub PeopleRepeater_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles PeopleRepeater.ItemDataBound
Dim NameLabel As Label = CType(e.Item.FindControl("LabelName"), Label)
NameLabel.Text = e.Item.DataItem("Name")
Dim TitleLabel As Label = CType(e.Item.FindControl("TitleName"), Label)
NameLabel.Text = e.Item.DataItem("Title")
Dim PhoneLabel As Label = CType(e.Item.FindControl("PhoneName"), Label)
NameLabel.Text = e.Item.DataItem("Phone")
Dim EmailLabel As Label = CType(e.Item.FindControl("EmailName"), Label)
NameLabel.Text = e.Item.DataItem("Email")
End Sub
Use a SqlDataAdapter:
Using adap As New SqlDataAdapter(oCommand)
Dim table As New DataTable()
adap.Fill(table)
PeopleRepeater.DataSource = table
PeopleRepeater.DataBind()
End Using
I don't see where you're opening the connection either, so you might need to add that:
oCommand.Connection.Open()
Follow the steps
Create the stored procedure named as 'SelectPersonalDetails'
CREATE PROCEDURE SelectPersonalDetails
-- Add the parameters for the stored procedure here
#Email SYSNAME
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
BEGIN TRY
BEGIN TRANSACTION
BEGIN
SELECT Name,Title,Phone,Email FROM PersonalDetails
WHERE
Email = #Email
END
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
DECLARE #ERR AS VARCHAR(500)
SELECT #ERR = ERROR_MESSAGE()
RAISERROR(#ERR,16,1)
RETURN
END CATCH
END
Create dataset in order to bind the data in the repeater.
public DataSet Get_PersonaldetailbasedEmail()
{
try
{
DataSet oDS = new DataSet();
SqlParameter[] oParam = new SqlParameter[1];
oParam[0] = new SqlParameter("#Email", _sEmail);
oDS = SqlHelper.ExecuteDataset(DataConnectionString, CommandType.StoredProcedure, "SelectPersonalDetails", oParam);
return oDS;
}
catch (Exception e)
{
ErrorMessage = e.Message;
return null;
}
}
Note: (i) SelectPersonalDetails is the stored procedure name
(ii) In order to select unique record from the table i have used emailid
(iii) I have assume the table name as PersonalDetails.
Create a user control page something like Personeldetails.ascx
/li>
/li>
/li>
/li>
Note above i have the html code for repeater but i don't know how to work around in this editor. anyways repeater id is same as your repeater and label ids are same as your label id.
Databind
Create a function to bind the data
public void FillArray(ArrayList alist)
{
ArrayList al = new ArrayList();
foreach (Object objRow in alist)
{
string sTitle = ((DataRow)objRow)["Title"].ToString();
string sName = ((DataRow)objRow)["Name"].ToString();
string sPhone = ((DataRow)objRow)["Phone"].ToString();
string sMail = ((DataRow)objRow)["Mail"].ToString();
al.Add(new string[]{ sTitle,sName,sPhone,sMail});
}
PeopleRepeater.DataSource = al;
PeopleRepeater.DataBind();
}
Now called Item databound
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
string[] itemArray = ((string[])e.Item.DataItem);
Label myTitle = (Lable)e.Item.FindControl("TitleLabel");
Label myName = (Label)e.Item.FindControl("NameLabel");
Label myPhone = (Label)e.Item.FindControl("PhoneLabel");
Label myEmail = (Label)e.Item.FindControl("EmailLabel");
myTitle.Text = itemArray[0];
myName.Text = itemArray[1];
myPhone.Text = itemArray[2];
myEmail.Text = itemArray[3];
}
If you find the answer useful, please mark it as your answer else let me know....

how do i display the "On Offer" indicator when the product is on offer in the database of asp.net?

I need to display the "on Offer" indicator next to the product in the gridview if the product has a number "1" in the "Offered" column in the database. if it is zero, then don't display. is there some way to achieve that? thanks.
In my product listing page:
Dim objCat As New Category
Dim objProduct As New Product
Dim i As Integer
Dim boolError As Boolean = False
objCat.ID = CType(Request.QueryString("CatID"), Integer)
' get details of the category
objCat.GetDetails()
' Display the category name
lblCatName.Text = objCat.Name
lblCatName2.Text = objCat.Name
' Display the category description
lblCatDesc.Text = objCat.Description
objCat.GetOfferedProducts()
For i = 0 To gvProduct.Rows.Count - 1
' Get the ProductId from the first cell
objProduct.ID = gvProduct.Rows(i).Cells(0).Text
Dim lblOffer As Label
lblOffer = CType(gvProduct.Rows(i).FindControl("lblOffer"), Label)
If objCat.Offered = "1" Then
lblOffer.Visible = True
Else
lblOffer.Visible = False
End If
Next
gvProduct.DataSource = objCat.GetProducts()
gvProduct.DataBind()
in my category class:
Public Sub GetOfferedProducts()
' Define a conection to database
' Read connection string from the web.config file.
Dim strConn As String
strConn = ConfigurationManager.ConnectionStrings("AppDb").ToString
Dim conn As New SqlConnection(strConn)
' Retrieve details of a given Category ID from the database
Dim strSql As String
strSql = "SELECT * FROM CatProduct cp INNER JOIN Product p " & _
"ON cp.ProductID=p.ProductID INNER JOIN Category c ON cp.CategoryID=c.CategoryID " & _
"WHERE cp.CategoryID=#CategoryID"
' Define an Command object to execute the SQL statement
Dim cmd As New SqlCommand(strSql, conn)
' Add parameter to the SQL command
cmd.Parameters.AddWithValue("#CategoryID", ID)
' Define a data adapter to fetch data
Dim da As New SqlDataAdapter(cmd)
' Define a data set to hold the data fetched
Dim ds As New DataSet
' Open database connection
conn.Open()
da.Fill(ds, "CatProduct")
' Close the database connection
conn.Close()
If ds.Tables("CatProduct").Rows.Count <> 0 Then
Name = ds.Tables("CatProduct").Rows(0)("CatName")
Description = ds.Tables("CatProduct").Rows(0)("CatDesc")
ImageFile = ds.Tables("CatProduct").Rows(0)("CatImage")
Offered = CType(ds.Tables("CatProduct").Rows(0)("Offered"), Integer)
End If
I would hook up the gridview's OnRowDataBound in your aspx page:
<asp:gridview id="MyGridView"
autogeneratecolumns="true"
allowpaging="true"
onrowdatabound="MyGridView_RowDataBound"
runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Label runat="server" id="lblOffer"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:gridview>
Then in the code behind you could do something like this:
void MyGridView_RowDataBound(Object sender, GridViewRowEventArgs e)
{
if(e.Row.RowType == DataControlRowType.DataRow)
{
var lbl = e.Row.FindControl("lblOffer");
If objCat.Offered = "1" Then
lbl.Visible = True
Else
lbl.Visible = False
End If
}
}
Hope that helps!!
There are various ways to make this happen. Basically, you're just looking to conditionally show/hide an element in the grid.
Which of the many ways to do this happens to be the best way entirely depends on how you're retrieving, binding to and displaying your data. You can put the logic in the business layer (a certain property is set or null based on business rules, etc.), in your data binding code (if you're looping through records for the display or something, such as in an ItemDataBound handler), in your display code (if you're just declaring everything in the aspx and just need to toss in an Eval and a conditional), etc.

switch statement in linq

My code for sql connection using linq is:
var query1 = from u in dc.Usage_Computers
where u.DomainUser == s3
select u; // selects all feilds from table
GridView1.DataSource = query1;
GridView1.DataBind();
I have a field called "Operation" in the table "Domainuser" which has values like "1, 2, 3". When I populate these values to data grid I wanted to convert them to meaningful values like if the value of Operation is 1 then display in datagrid as "logon", if 2 then "logoff" etc...
How do i assign values for them after retrieving from database?
This technique does not seem particularly applicable to your problem, but here it is anyway.
You can create a SQL case statement in LinqToSql by using the C# ? : operator.
var query1 =
from u in dc.Usage_Computers
where u.DomainUser == s3
select new {usage = u,
operation =
u.DomainUser.Operation == 1 ? "login" :
u.DomainUser.Operation == 2 ? "logoff" :
"something else"
};
Use a template field in your gridview:
<asp:GridView ID="gvDomain" runat="server" OnRowDataBound="gvDomain_RowDataBound">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
Operation
</HeaderTemplate>
<ItemTemplate>
<asp:Label id="lblLogon" runat="server" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Then use the gridviews RowDataBound event to discover the label and assign its text:
Protected Sub gvDomain_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles gvStates.RowDataBound
Dim lblLogon As Label = DirectCast(e.Row.FindControl("lblLogon"), Label)
Dim drv As DataRowView = DirectCast(e.Row.DataItem, DataRowView)
If lblLogon IsNot Nothing Then
Select Case drv("Operation").ToString()
Case "1"
lblLogon.Text = "Logon"
Break
Case "2"
lblLogon.Text = "Logoff"
Break
//etc...
End Select
End If
End Sub
static Func<int?, string> MapSqlIntToArbitraryLabel = (i =>
{
// for performance, abstract this reference
// dictionary out to a static property
Dictionary<int, string> labels = new Dictionary<int, string>();
labels.Add(1, "logon");
labels.Add(2, "logoff");
labels.Add(...);
if (i == null) throw new ArgumentNullException();
if (i < 1 || i > labels.Count) throw new ArgumentOutOfRangeException();
return labels.Where(x => x.Key == i.Value)
.Select(x.Value)
.Single();
}
that return statement can also be expressed as:
return (from kvp in labels
where kvp.Key == i.Value
select kvp.Value).Single();
Then you can use call that function from your linq query like so:
var query1 = from u in dc.Usage_Computers
where u.DomainUser == s3
select {
Operation = MapSqlIntToArbitraryLabel(u.Operation)
// add other properties to this anonymous type as needed
};
I've tried every suggested method of fooling Linq2Sql into running my code and this method is the only one that i've found that allows me to run code as part of a deferred-execution projection.
I've done something similar using TemplateFields. Using an ASP:Label bound to the property and adding an OnPreRender event handler for the control. In the event handler for the control I translate the text based on it's current value and set the new value:
protected void label_OnPreRender( object sender, EventArgs e )
{
Label l = (Label)sender;
switch (l.Text) {
case "1":
l.Text = "Logon";
break;
...
default:
break;
}
}
If the form is in edit mode, you'll need to handle it differently. You'll also probably need to add handlers for Inserting and Updating to the View control you are using to translate the data supplied by the page into its database representation.

Resources