URGENT URGENT print question. and will be merge for 1000 points.

<asp:TemplateColumn>
                                    <ItemTemplate>
      <asp:Button CommandName="Print" Text="Print" Runat="server" ID="Button2"></asp:Button>
                                    </ItemTemplate>
                              </asp:TemplateColumn>

if(e.CommandName =="Print")
                  {
                        string parsedreceipt = null;
                        parsedreceipt = DecodeReceipt (e.Item.Cells[3].Text);
                        *****=> Print to printer what ever way.
                        
                  }
                        


.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Drawing;
using System.Data.Common;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using Microsoft.Data.Odbc;
namespace MSPOS
{
      /// <summary>
      /// Summary description for Receipts.
      /// </summary>
      public class Receipts : System.Web.UI.Page
      {
            protected System.Web.UI.WebControls.RadioButtonList Group_RadioButtonList;
            protected System.Web.UI.WebControls.DataGrid ReceiptsDataGrid;
            private DataSet ddlDataSet = new DataSet();
            private OdbcConnection myConnection =  new OdbcConnection("DSN=POS;UID=system;PWD=system");
            protected System.Web.UI.WebControls.Button btnRunQuery;
            protected System.Web.UI.WebControls.Button Button2;
            
            protected System.Web.UI.WebControls.TextBox txtPayment;
            protected System.Web.UI.WebControls.TextBox txtCashier;
            
            private DataSet ddlDataSet1 = new DataSet();
            private DataSet ddlDataSet2 = new DataSet();
            protected ActiveUp.WebControls.ActiveDateTime ActiveDateTime3;
            protected ActiveUp.WebControls.ActiveDateTime ActiveDateTime4;
            private DataSet ddlDataSet3 = new DataSet();
 
            private void Page_Load(object sender, System.EventArgs e)
            {
                  // Put user code to initialize the page here
                  if (!Page.IsPostBack)
                  {
                        ActiveDateTime3.Date = System.DateTime.Today.Date;
                        ActiveDateTime4.Date = System.DateTime.Today.Date;
                  }
            }

            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                  //
                  // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                  //
                  InitializeComponent();
                  base.OnInit(e);
            }
            
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {    
                  this.Group_RadioButtonList.SelectedIndexChanged += new System.EventHandler(this.Group_RadioButtonList_SelectedIndexChanged);
                  this.txtCashier.TextChanged += new System.EventHandler(this.txtCashier_TextChanged);
                  this.btnRunQuery.Click += new System.EventHandler(this.btnRunQuery_Click);
                  this.ReceiptsDataGrid.SelectedIndexChanged += new System.EventHandler(this.ReceiptsDataGrid_SelectedIndexChanged);
                  this.Load += new System.EventHandler(this.Page_Load);

            }
            #endregion

            private string DecodeReceipt (string szBill)
            {
                  string szNewBill="";
                             
                  // Create an ASCII encoding.
                  Encoding ascii = Encoding.ASCII;
                       
                  Byte[] encodedBytes = ascii.GetBytes(szBill);

                  foreach (Byte a in encodedBytes)
                  {
                        if ( a ==10 || a ==15 ||a==18 ||a ==27)
                        {}          
                        else if (a == 13)
                              szNewBill = szNewBill + "\\n";
                        else
                              szNewBill = szNewBill +(char) a;

                  }
                  return szNewBill;
            }
         


            private void txtPayment_TextChanged(object sender, System.EventArgs e)
            {
            
            }

            private void txtCashier_TextChanged(object sender, System.EventArgs e)
            {
            
            }

            //***********************************************************************
            // Get RC_PAYMND and populate dataset
            public DataSet BindRC_PAYMND(string searchstring)
            {
                  OdbcConnection myConnection =  new OdbcConnection("DSN=POS;UID=system;PWD=system");

                  // Populate the ddlDataSet1
                  myConnection.Open();
                  string strSQLDDL = @"SELECT RC_PAYMNB FROM TBRECEIPTS WHERE RC_PAYMNB='"+searchstring+"'";
                  OdbcDataAdapter myDataAdapter = new OdbcDataAdapter(strSQLDDL, myConnection);
                  ddlDataSet1.Clear();  
                  myDataAdapter.Fill(ddlDataSet1, "ddlRC_PAYMNB");
                  myDataAdapter.Dispose();
                  myDataAdapter = null;
                  myConnection.Close();
                  strSQLDDL = null;
                  return ddlDataSet1;
            }
            //***********************************************************************

            //***********************************************************************
            // Get RC_CASHND and populate dataset
            public DataSet BindRC_CASHND(string searchstring)
            {
                  OdbcConnection myConnection =  new OdbcConnection("DSN=POS;UID=system;PWD=system");

                  // Populate the ddlDataSet2
                  myConnection.Open();
                  string strSQLDDL = @"SELECT RC_CASHNB FROM TBRECEIPTS WHERE RC_CASHNB='"+searchstring+"'";
                  OdbcDataAdapter myDataAdapter = new OdbcDataAdapter(strSQLDDL, myConnection);
                  ddlDataSet2.Clear();  
                  myDataAdapter.Fill(ddlDataSet2, "ddlRC_CASHNB");
                  myDataAdapter.Dispose();
                  myDataAdapter = null;
                  myConnection.Close();
                  strSQLDDL = null;
                  return ddlDataSet2;
            }
            //***********************************************************************


            //***********************************************************************
            // Get RC_CASHND and populate dataset with RC_CASHND and RC_DATE
            public DataSet BindRC_DATE()
            {
                  OdbcConnection myConnection =  new OdbcConnection("DSN=POS;UID=system;PWD=system");

                  // Populate the ddlDataSet3
                  myConnection.Open();
                  string strSQLDDL = @"SELECT RC_DATE FROM TBRECEIPTS";
                  OdbcDataAdapter myDataAdapter = new OdbcDataAdapter(strSQLDDL, myConnection);
                  ddlDataSet3.Clear();  
                  myDataAdapter.Fill(ddlDataSet3, "ddlRC_DATE");
                  myDataAdapter.Dispose();
                  myDataAdapter = null;
                  myConnection.Close();
                  strSQLDDL = null;
                  return ddlDataSet3;
            }
            //***********************************************************************


            public void ReceiptsDataGrid_ItemCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
            {
                  ListItemType oType = ((ListItemType)e.Item.ItemType);
                  if(oType == ListItemType.Item || oType == ListItemType.AlternatingItem)
                  {
                        e.Item.Attributes.Add("onmouseover", "this.style.backgroundColor='lightblue'");            
                        e.Item.Attributes.Add("onmouseout", "this.style.backgroundColor='Beige'");            
                  }
                  
                  if(e.CommandName =="View")
                  {
                        string parsedreceipt = null;
                        parsedreceipt = DecodeReceipt (e.Item.Cells[3].Text);
                        StringBuilder strAlert = new StringBuilder();
                        strAlert.Append("<script language=javascript> alert('");
                        strAlert.Append("Receipt:                    " + parsedreceipt + "\\n");
                        strAlert.Append("');</script>");
                        this.RegisterStartupScript("startup",strAlert.ToString());
                  }

                  if(e.CommandName =="Print")
                  {
                        string parsedreceipt = null;
                        parsedreceipt = DecodeReceipt (e.Item.Cells[3].Text);
                        Response.Write("<script language=\"JavaScript\">");
                        Response.Write("</script>");
                        
                  }
                        
                  

            }


            private void Group_RadioButtonList_SelectedIndexChanged(object sender, System.EventArgs e)
            {
            
            }


            public void btnRunQuery_Click(object sender, System.EventArgs e)
            {
                  string select_statement = "SELECT RC_PAYMNB, RC_CASHNB, RC_DATE, RC_DATA FROM TBRECEIPTS";
                  string DateString1 = ActiveDateTime3.Date.Day.ToString() + "-" + ActiveDateTime3.Date.Month.ToString() + "-" + ActiveDateTime3.Date.Year.ToString();
                  string DateString2 = ActiveDateTime4.Date.Day.ToString() + "-" + ActiveDateTime4.Date.Month.ToString() + "-" + ActiveDateTime4.Date.Year.ToString();

                  Response.Write (DateString1 +"<BR>");
                  Response.Write (DateString2 +"<BR>");
                  
                  switch (Group_RadioButtonList.SelectedIndex)
                  {
                        case 0:
                              select_statement += " Where RC_PAYMNB='" + txtPayment.Text + "'";
                              break;
                        case 1:
                              select_statement += " Where RC_CASHNB='" + txtCashier.Text + "'";
                              break;
                        case 2:
                              select_statement += " Where RC_DATE<='" + ActiveDateTime4.Date + "' And RC_DATE >= '" + ActiveDateTime3.Date + "'"; //i don't know the type of these fields so this is the reason that i use text property
                              break;
                  }


                  OdbcConnection myConnection =  new
                  OdbcConnection("DSN=POS;UID=system;PWD=system");

                  // Populate the ddlDataSet1
                  myConnection.Open();
                  string strSQLDDL = select_statement;
                  OdbcDataAdapter myDataAdapter = new OdbcDataAdapter(strSQLDDL,myConnection);
                  ddlDataSet1.Clear();  
                  myDataAdapter.Fill(ddlDataSet1);
                  myDataAdapter.Dispose();
                  myDataAdapter = null;
                  myConnection.Close();
                  ReceiptsDataGrid.DataSource = ddlDataSet1.Tables[0];
                  ReceiptsDataGrid.DataBind();
            
        }

            private void ReceiptsDataGrid_SelectedIndexChanged(object sender, System.EventArgs e)
            {
            
            }
            

      }
}


.aspx


<%@ Register TagPrefix="mspos" TagName="footer" Src="~/Engine/Controls/footer.ascx" %>
<%@ Register TagPrefix="mspos" TagName="header" Src="Engine/Controls/header.ascx" %>
<%@ Register TagPrefix="uc1" TagName="logout" Src="Engine/Controls/logout.ascx" %>
<%@ Page Language="c#" trace="true" Codebehind="Receipts.aspx.cs" AutoEventWireup="false" Inherits="MSPOS.Receipts" CompilerOptions='/R:"C:\Program Files\Microsoft.NET\Odbc.Net\Microsoft.data.odbc.dll"'%>
<%@ Register TagPrefix="cc1" Namespace="ActiveUp.WebControls" Assembly="ActiveDateTime" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
      <HEAD>
<script language="JavaScript">

</script>
      </HEAD>
      <body leftMargin="0" background="images/bg.gif" topMargin="0" marginheigh="0" marginwidth="0">
            <form id="Form1" action="database.aspx" method="post" runat="server">
                  <strong>
                        <P><mspos:header id="Header1" runat="server"></mspos:header><BR>
                              <FONT face="Verdana" size="2"></FONT>
                        </P>
                        <P><FONT face="Verdana" size="2"></FONT>&nbsp;</P>
                        <FONT face="Verdana" size="2">
                              <P>
                                    <TABLE id="Table2" height="118" cellSpacing="1" cellPadding="1" width="355" border="0">
                                          <TR>
                                                <TD vAlign="top" width="147" colSpan="1" rowSpan="4">
                                                      <P><asp:radiobuttonlist id="Group_RadioButtonList" runat="server" BorderWidth="0px" CellSpacing="1" CellPadding="1"
                                                                  Height="111px" Font-Bold="True" Font-Size="12px" Font-Names="Verdana" Width="35px" BackColor="#FEF9E9">
                                                                  <asp:ListItem Value="PayNumber">1</asp:ListItem>
                                                                  <asp:ListItem Value="Cashier">2</asp:ListItem>
                                                                  <asp:ListItem Value="StartDate">3</asp:ListItem>
                                                            </asp:radiobuttonlist></P>
                                                      &nbsp;&nbsp;
                                                </TD>
                                                <TD noWrap colSpan="1" rowSpan="1">Payment Number:</TD>
                                                <TD vAlign="middle" noWrap width="200" colSpan="1" rowSpan="1"><asp:textbox id="txtPayment" runat="server" MaxLength="10"></asp:textbox></TD>
                                          </TR>
                                          <TR>
                                                <TD width="240">Cashier Number:</TD>
                                                <TD><asp:textbox id="txtCashier" runat="server" MaxLength="8"></asp:textbox></TD>
                                          </TR>
                                          <TR>
                                                <TD width="240" height="10">Start Date:</TD>
                                                <TD height="10"><cc1:activedatetime id="ActiveDateTime3" runat="server" AllowNull="False" MonthNamesDisabled="True"
                                                            Format="DAY;-;MONTH;-;YEAR"></cc1:activedatetime></TD>
                                          </TR>
                                          <TR>
                                                <TD width="240">End Date:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                                                </TD>
                                                <TD><cc1:activedatetime id="ActiveDateTime4" runat="server" AllowNull="False" MonthNamesDisabled="True"
                                                            Format="DAY;-;MONTH;-;YEAR"></cc1:activedatetime></TD>
                                          </TR>
                                          <TR>
                                                <TD width="240"></TD>
                                                <TD><asp:button id="btnRunQuery" onclick="btnRunQuery_Click" runat="server" text="Run Query" type="submit"></asp:button></TD>
                                          </TR>
                                    </TABLE>
                        </FONT></strong>
                  <br>
                  <strong>Results of:</strong>
                  <asp:datagrid id="ReceiptsDataGrid" runat="server" BorderWidth="3" CellSpacing="1" CellPadding="1"
                        Height="144px" Width="500px" OnItemCommand="ReceiptsDataGrid_ItemCommand" HeaderStyle-Font-Bold="True"
                        maintainviewstate="false" GridLines="None" BorderStyle="Outset" font-size="XX-Small" font-names="Verdana"
                        BorderColor="#CCCC99" AutoGenerateColumns="False">
                        <AlternatingItemStyle Wrap="False" BackColor="PaleGoldenrod"></AlternatingItemStyle>
                        <ItemStyle Wrap="False" BackColor="Beige"></ItemStyle>
                        <HeaderStyle Font-Size="14px" Font-Bold="True" ForeColor="White" BackColor="#954896"></HeaderStyle>
                        <Columns>
                              <asp:BoundColumn DataField="RC_PAYMNB" HeaderText="Payment Number "></asp:BoundColumn>
                              <asp:BoundColumn DataField="RC_CASHNB" HeaderText="Cash Number"></asp:BoundColumn>
                              <asp:BoundColumn DataField="RC_DATE" HeaderText="Date"></asp:BoundColumn>
                              <asp:BoundColumn DataField="RC_DATA" Visible="False" HeaderText="Data"></asp:BoundColumn>
                              <asp:TemplateColumn>
                                    <ItemTemplate>
                                          <asp:Button CommandName="View" Text="View" Runat="server" ID="Button1"></asp:Button>
                                    </ItemTemplate>
                              </asp:TemplateColumn>
                              <asp:TemplateColumn>
                                    <ItemTemplate>
                                          <asp:Button CommandName="Print" Text="Print" Runat="server" ID="Button2"></asp:Button>
                                    </ItemTemplate>
                              </asp:TemplateColumn>
                        </Columns>
                  </asp:datagrid></P></form>
      </body>
</HTML>

mathieu_cuprykAsked:
Who is Participating?
 
der_jthConnect With a Mentor Commented:
Your code uses "\\n"; you should use just "\n" instead (only one backslash). If it doesn't work for you, use "\r\n". I'll be going to sleep now -- if you can't make it work, let's see more tomorrow.
0
 
der_jthCommented:
Do you want it to be printed at the client or the server end? If client, open the decoded receipt document in a browser window and call the Javascript function window.print() in the OnLoad event of the document. If server, take a look at <http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbconprintsupport.asp>. If you need further help, please be more specific.
0
 
mathieu_cuprykAuthor Commented:
On the client side

I need a javascript with a the string being passed.
parsedreceipt

It can open up a dialog box. What have u. It just needs to work.

Response.Write("<script language=\"JavaScript\">");
**************=>>>>>>>>>>>>>.
Response.Write("</script>");
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
mathieu_cuprykAuthor Commented:
It is a client side script.  It is a webform. Do u need more information.
0
 
der_jthCommented:
Try redirecting the user to a new aspx page with the following page content:
--
<html>
<body>
<pre>
<%=Server.HtmlEncode(decodedReceiptHere)%>
</pre>
<script language="JavaScript">
window.print();
</script>
</body>
</html>
0
 
mathieu_cuprykAuthor Commented:
How do I call this:


                  if(e.CommandName =="Print")
                  {
                        string parsedreceipt = null;
                        parsedreceipt = DecodeReceipt (e.Item.Cells[3].Text);
                                                
                  }
0
 
mathieu_cuprykAuthor Commented:
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.

Compiler Error Message: CS1501: No overload for method 'DecodeReceipt' takes '0' arguments

Source Error:

 

Line 11:       <body leftMargin="0" background="images/bg.gif" topMargin="0" marginheigh="0" marginwidth="0">
Line 12:             <pre>
Line 13: <%=Server.HtmlEncode(DecodeReceipt ())%>
Line 14: </pre>
Line 15: <script language="JavaScript">
 
0
 
der_jthCommented:
The correct approach depends heavily on what you're doing, but the following will work in most cases. It is pretty ugly though :-(

--
              if(e.CommandName =="Print")
               {
                    Session["parsedReceipt"] = DecodeReceipt (e.Item.Cells[3].Text);                                        
                    Response.Redirect("printreceipt.aspx");
               }
--

And printreceipt.aspx should be something like the following:

--
<%@Page language="C#"%>
<html>
<body>
<html>
<body>
<pre>
<%=Server.HtmlEncode(Session["parsedReceipt"])%>
</pre>

<hr>

<p><a href="/">Return</a> to the main application.</p>

<script language="JavaScript">
window.print();
</script>

</body>
</html>
0
 
mathieu_cuprykAuthor Commented:
Compilation Error
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.

Compiler Error Message: CS1502: The best overloaded method match for 'System.Web.HttpServerUtility.HtmlEncode(string)' has some invalid arguments

Source Error:

 

Line 11:       <body>
Line 12:             <pre>
Line 13: <%=Server.HtmlEncode(Session["parsedReceipt"])%>
Line 14: </pre>
Line 15:             <hr>
 

Source File: C:\Inetpub\wwwroot\MSPOS\PrintReceipt.aspx    Line: 13



Show Detailed Compiler Output:


c:\windows\system32\inetsrv> "c:\windows\microsoft.net\framework\v1.1.4322\csc.exe" /t:library /utf8output /R:"c:\windows\assembly\gac\system.drawing\1.0.5000.0__b03f5f7f11d50a3a\system.drawing.dll" /R:"c:\windows\assembly\gac\system.web.mobile\1.0.5000.0__b03f5f7f11d50a3a\system.web.mobile.dll" /R:"c:\windows\assembly\gac\system.data\1.0.5000.0__b77a5c561934e089\system.data.dll" /R:"c:\windows\assembly\gac\system.enterpriseservices\1.0.5000.0__b03f5f7f11d50a3a\system.enterpriseservices.dll" /R:"c:\windows\microsoft.net\framework\v1.1.4322\temporary asp.net files\mspos\103692e3\19bdc9e7\assembly\dl2\412fda75\c0b65432_45b5c401\mspos.dll" /R:"c:\windows\microsoft.net\framework\v1.1.4322\temporary asp.net files\mspos\103692e3\19bdc9e7\qgs_ahkr.dll" /R:"c:\windows\microsoft.net\framework\v1.1.4322\mscorlib.dll" /R:"c:\windows\assembly\gac\system.web\1.0.5000.0__b03f5f7f11d50a3a\system.web.dll" /R:"c:\windows\assembly\gac\system\1.0.5000.0__b77a5c561934e089\system.dll" /R:"c:\windows\microsoft.net\framework\v1.1.4322\temporary asp.net files\mspos\103692e3\19bdc9e7\assembly\dl2\18b8a94a\4e887d3b_0eb5c401\activedatetime.dll" /R:"c:\windows\assembly\gac\system.web.services\1.0.5000.0__b03f5f7f11d50a3a\system.web.services.dll" /R:"c:\windows\assembly\gac\system.xml\1.0.5000.0__b77a5c561934e089\system.xml.dll" /out:"C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files\mspos\103692e3\19bdc9e7\f9cx1ydn.dll" /D:DEBUG /debug+ /optimize- /warnaserror /w:1  "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files\mspos\103692e3\19bdc9e7\f9cx1ydn.0.cs"


Microsoft (R) Visual C# .NET Compiler version 7.10.6001.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.

C:\Inetpub\wwwroot\MSPOS\PrintReceipt.aspx(13,28): error CS1502: The best overloaded method match for 'System.Web.HttpServerUtility.HtmlEncode(string)' has some invalid arguments
C:\Inetpub\wwwroot\MSPOS\PrintReceipt.aspx(13,46): error CS1503: Argument '1': cannot convert from 'object' to 'string'

 

0
 
der_jthCommented:
Oops, sorry :-( I tested the code prior to adding the html encoding and forgot that it requires a strnig instead of an object. Use

<%=Server.HtmlEncode(Session["parsedReceipt"].ToString())%>

instead.

Also, in order to avoid spurious runtime errors when users enter the page without a valid receipt, you can also throw in a

<%
  if (Session["parsedReceipt"] == null) Response.Redirect("/");
%>

right after the <%@ Page%> directive.
0
 
mathieu_cuprykAuthor Commented:
The problem is in here:

      <body>
            <pre>
<%=Server.HtmlEncode(Session["ParsedReceipt"].ToString())%>
</pre>

Not parsing. Properly.
0
 
der_jthCommented:
What do you mean by that? It works fine with me. Please, always post error messages if you say something doesn't work.
0
 
mathieu_cuprykAuthor Commented:
It's almost there but it is an empty string:
Omg u almost have it.
if(e.CommandName =="Print")
{
                        string parsedreceipt = null;
                        parsedreceipt = DecodeReceipt (e.Item.Cells[3].Text);
                        Session["ParsedReceipt"] = parsedreceipt;                                      
                        Response.Redirect("PrintReceipt.aspx");
                        
}

<html>
      <body>
            <pre>
<%
  if (Session["ParsedReceipt"] == null) Response.Redirect("/");
%>
</pre>
            <hr>
            <p><a href="/">Return</a> to the main application.</p>
            <script language="JavaScript">
window.print();
            </script>
      </body>
</html>
0
 
der_jthCommented:
Some very minor errors only... The nullity check should be separate from the value printing (and encoding). This should work as your aspx file content:

--
<%@Page language="C#"%>
<% if (Session["parsedReceipt"] == null) Response.Redirect("/"); %>

<html>
<body>
<pre>
<%=Server.HtmlEncode(Session["parsedReceipt"].ToString())%>
</pre>

<hr>

<p><a href="/">Return</a> to the main application.</p>

<script language="JavaScript">
window.print();
</script>

</body>
</html>
0
 
mathieu_cuprykAuthor Commented:
Ok
T S T T        \nIND.SQUARE/EDWARD ST\nVAT REG# 100476     \nBill Payment  2004/07/1          100.00 \nAccount:   91013698-0000                \n      Chantal Rigaud                    \nA/c Balance:  2,566.33                  \n                                        \n                                        \nTOTAL                            100.00 \n                                        \nTENDERED                                \n Cash                   100.00          \n    TOTAL TENDERED               100.00 \n                                        \nCHANGE                             0.00 \n


We should fix \n
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.