Problem when inserting data in windows form c # form with sql

0

I am developing a program that I am doing for my class, it is a small program of a hardware store where product information is kept, clients (so that if it is a distributor, apply discount) , types of products and so on.

The problem is in the billing section; sometimes it allows me to keep the invoice and sometimes not, and I do not know what to do, I've tried everything I can know, but nothing.

This is my source code:

protected override void Inicializar()
{
    base.Inicializar();

    // Llenamos el comboBox de Clientes
    CargarClientes();

    if (param_codigo == 0)
    {
        // Nuevo Registro
        NuevaFactura();
    }
    else
    {
        // Registro ya Existente
        btnAdicionarProducto.Enabled = false;

        VerFactura();
    }
}

private void CargarClientes()
{
    DataTable dt = null;
    string cadena_sql = "";
    cadena_sql = @"SELECT codigo, nombre_cliente 
                   FROM Clientes ";

    if (global.conn.SQLSelectDataTable(cadena_sql, ref dt))
    {
        cmbCodigoCliente.DataSource = dt;
    }
}

private void NuevaFactura()
{
    string cadena_sql = "";
    DataRow dr = null;
    int numero_factura = 0;

    cadena_sql = @"SELECT ISNULL(max(numero_factura),0) as maximo
                   FROM Facturas";

    if (global.conn.SQLSelectDataRow(cadena_sql, ref dr))
    {
        numero_factura = Convert.ToInt32(dr["maximo"]);
        numero_factura = numero_factura + 1;
        txtNumeroFactura.Text = numero_factura.ToString();
    }
}

private void VerFactura()
{
    VerEncabezado();
    VerDetalle();
}

private void VerEncabezado()
{
    DataRow dr = null;
    string cadena_sql = "";

    cadena_sql = @"SELECT * 
                   FROM Facturas
                   WHERE codigo = {0}";

    cadena_sql = string.Format(cadena_sql, param_codigo);

    if (global.conn.SQLSelectDataRow(cadena_sql, ref dr))
    {
        txtCodigo.Text = dr["codigo"].ToString();
        txtNumeroFactura.Text = dr["numero_factura"].ToString();
        dtpFecha.Value = Convert.ToDateTime(dr["fecha"]);
        cmbCodigoCliente.SelectedValue = Convert.ToInt32(dr["codigo_cliente"]);

        txtSubtotal.Text = Convert.ToDouble(dr["subtotal"]).ToString("###,###.00");
        txtImpuesto.Text = Convert.ToDouble(dr["impuesto"]).ToString("###,###.00");
        txtTotal.Text = Convert.ToDouble(dr["total"]).ToString("###,###.00");
    }
}

private void VerDetalle()
{
    string cadena_sql = "";
    DataTable dt = null;

    cadena_sql = @"SELECT 
                    fd.numero_linea
                    ,fd.codigo_producto
                    ,p.nombre as nombre_producto
                    ,fd.cantidad
                    ,fd.precio
                    ,(fd.cantidad * fd.precio) as total_item
                    FROM
                    FacturasDetalle fd
                    join
                    Productos p
                    on
                    fd.codigo_producto = p.codigo
                    WHERE
                    fd.codigo_factura = {0}
                    ";

    cadena_sql = string.Format(cadena_sql, param_codigo);

    if (global.conn.SQLSelectDataTable(cadena_sql, ref dt))
    {
        dgvDetalle.DataSource = dt;
    }
}

private void Totales()
{
    // Objetivo:
    // Recorrer el detalle, calcular total item
    // Sumarizar Subtotal, impuesto y total

    double cantidad = 0;
    double precio = 0;
    double total_item = 0;

    double subtotal = 0;
    double impuesto = 0;
    double total = 0;

    foreach (DataGridViewRow r in dgvDetalle.Rows)
    {
        cantidad = Convert.ToDouble(r.Cells["nCantidad"].Value);
        precio = Convert.ToDouble(r.Cells["nPrecio"].Value);
        total_item = cantidad * precio;
        r.Cells["nTotalItem"].Value = total_item;
        subtotal = subtotal + total_item;
    }

    // Calculamos impuesto y total
    impuesto = subtotal * 0.15;

    total = subtotal + impuesto;

    txtSubtotal.Text = subtotal.ToString("###,###.00");
    txtImpuesto.Text = impuesto.ToString("###,###.00");
    txtTotal.Text = total.ToString("###,###.00");
}


private void AdicionarProducto()
{
    try
    {
        int codigo_producto = 0;
        int indice_nuevo = 0;
        int numero_fila = 0;
        string nombre_producto = "";
        double precio_producto = 0;
        string cadena_sql = "";
        DataRow dr = null;                
        frmProductos prods = new frmProductos();
        prods.modo_actual = frmLista.ModoApertura.Busqueda;
        prods.ShowDialog(this);
        codigo_producto = prods.codigo_seleccionado;

        if (codigo_producto > 0)
        {
            // Agregamos una fila
            cadena_sql = @"SELECT nombre, precio
                            FROM productos 
                            WHERE codigo = {0}";
            cadena_sql = string.Format(cadena_sql, codigo_producto);

            if (global.conn.SQLSelectDataRow(cadena_sql, ref dr))
            {
                nombre_producto = dr["nombre"].ToString();
                precio_producto = Convert.ToDouble(dr["precio"]);
                indice_nuevo = dgvDetalle.Rows.Add();
                dgvDetalle.Rows[indice_nuevo].Cells["nNumeroLinea"].Value = indice_nuevo + 1;
                dgvDetalle.Rows[indice_nuevo].Cells["nCodigoProducto"].Value = codigo_producto;
                dgvDetalle.Rows[indice_nuevo].Cells["sNombreProducto"].Value = nombre_producto;
                dgvDetalle.Rows[indice_nuevo].Cells["nCantidad"].Value = 1;
                dgvDetalle.Rows[indice_nuevo].Cells["nPrecio"].Value = precio_producto;
                dgvDetalle.Rows[indice_nuevo].Cells["nTotalItem"].Value = precio_producto;

                // Llamamos a la funcion de Totales
                Totales();
            }
        }
    }
    catch (Exception ex)
    {
    }
}

private void btnAdicionarProducto_Click(object sender, EventArgs e)
{
    AdicionarProducto();
}

private void dgvDetalle_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
    Totales();
}

private void frmFactura_Load(object sender, EventArgs e)
{

}

protected override void AccionGuardar()
{
    if (param_codigo > 0)
    {
        MessageBox.Show("Factura no se puede editar");
        return;
    }

    if (GuardarEncabezado())
    {
        GuardarDetalle();
    }
}

private bool GuardarEncabezado()
{
    try
    {
        DataRow dr = null;
        int codigo = 0;
        string cadena_sql = "";

        cadena_sql = @"INSERT INTO [dbo].[Facturas]
                   ([numero_factura],
                   [codigo_cliente],
                   [fecha],
                   [subtotal],
                   [impuesto],
                   [total])
             VALUES
                   (
                    {0},
                    {1},
                    '{2}',
                    {3},
                    {4},
                    {5})";


        cadena_sql = string.Format(
                    cadena_sql,
                    txtNumeroFactura.Text,
                    cmbCodigoCliente.SelectedValue,
                    dtpFecha.Value.ToString("yyyyMMdd"),
                    Convert.ToDouble(txtSubtotal.Text),
                    Convert.ToDouble(txtImpuesto.Text),
                    Convert.ToDouble(txtTotal.Text)
                    );

        if (global.conn.SqlExec(cadena_sql))
        {
            cadena_sql = @"SELECT MAX(codigo) as maximo
                           FROM Facturas";

            if (global.conn.SQLSelectDataRow(cadena_sql, ref dr))
            {
                codigo = Convert.ToInt32(dr["maximo"]);
                txtCodigo.Text = codigo.ToString();
                return true;
            }
        }
        else
        {
            MessageBox.Show("Error al guardar encabezado: " + global.conn.SQLError() );
        }


    }
    catch (Exception ex)
    {

    }

    return false;
}

private void GuardarDetalle()
{
    try
    {
        int codigo_factura = 0;
        string cadena_base = "";
        string cadena_sql = "";

        codigo_factura = Convert.ToInt32(txtCodigo.Text);

        cadena_base = @"INSERT INTO 
                        FacturasDetalle
                       (codigo_factura
                       ,numero_linea
                       ,codigo_producto
                       ,cantidad
                       ,precio)
                 VALUES
                       (
                        {0}
                        ,{1}
                        ,{2}
                        ,{3}
                        ,{4}
                        )";

        foreach(DataGridViewRow r in dgvDetalle.Rows)
        {
            cadena_sql = string.Format(cadena_base
                      , codigo_factura
                      , Convert.ToInt32(r.Cells["nNumeroLinea"].Value)
                      , Convert.ToInt32(r.Cells["nCodigoProducto"].Value)
                      , Convert.ToDouble(r.Cells["nCantidad"].Value)
                      , Convert.ToDouble(r.Cells["nPrecio"].Value)
                      );

            if (! (global.conn.SqlExec(cadena_sql)) )
            {
                MessageBox.Show("Error al guardar detalle: " + global.conn.SQLError());
            }
        }

        MessageBox.Show("Factura Guardada con Exito");
        this.Close();
    }
    catch (Exception ex)
    {
    }
}

And the error is as follows:

    
asked by Sergio Rivera 26.08.2016 в 05:20
source

2 answers

1

Let me guess. When you enter quantities without decimals it does not give you an error ... When using String.Format (...) you are substituting {i} for what you have in the textbox. Note that in the textbox you are entering "30.30". That is building a chain with more values than those expressed in the Insert clause. That is, the '30' takes it as a value and the '30' as a different since they are separated by commas. The Convert.ToDouble () does not solve it because it converts it to the default culture format. By using the ',' (which is the culture that you have set by default) you put it back in ',' when you do the String.Format () even using the '.' in your textbox or replace it with the replace () method before doing the Convert.

Solution (edited): Use an invariable culture for the conversion in the string.Format:

cadena_sql = string.Format(System.Globalization.CultureInfo.InvariantCulture,
                    cadena_sql,
                    txtNumeroFactura.Text,
                    cmbCodigoCliente.SelectedValue,
                    dtpFecha.Value.ToString("yyyyMMdd"),
                    Convert.ToDouble(txtSubtotal.Text),
                    Convert.ToDouble(txtImpuesto.Text),
                    Convert.ToDouble(txtTotal.Text)
                    );

The good solution would be to use parameters in the query and also avoid SQL Injection attacks. But as you say you are learning you can try this solution that I have proposed.

Greetings

    
answered by 26.08.2016 в 18:01
0

The error indicates that the number of columns declared in the INSERT statement are less than the number of values specified in the VALUES clause.

Review the INSERT instructions you're using well.

    
answered by 26.08.2016 в 16:37