none
Error al leer un excel en c# RRS feed

  • Pregunta

  • Buenas Tardes amigos

    tengo este error al leer un excel en c# en la maquina del Cliente en mi maquina servidor si funciona

    Como puedo solucionarlo

    Saludos


    ruben

    jueves, 26 de octubre de 2017 16:40

Respuestas

  • Vale,

    Creo que ya tengo la solucion.

    Lo primero de todo, es que mediante NuGet, añadas los paquetes:

    • DocumentFormat.OpenXml -> Version 2.5.0
    • SpreadsheetLight -> Version 3.4.9

    Una vez que tengas listo eso, añades este using:

    using SpreadsheetLight;

    Ahora, para leer el Excel, vamos a añadir un metodo

    DataTable LeerExcel(string strPath, string strSheet)
            {
                DataTable ret;
                int row;
                int column;
                int colPos = 0;
                using (SLDocument sl = new SLDocument(strPath, strSheet))
                {
                    
                    SLWorksheetStatistics stats = sl.GetWorksheetStatistics();
                    int iStartColumnIndex = stats.StartColumnIndex;
                    int iStartRowIndex = stats.StartRowIndex;
                    int iEndColumnIndex = stats.EndColumnIndex;
                    int iEndRowIndex = stats.EndRowIndex;
    
                    ret = new DataTable("Excel");
    
                    for (row = iStartRowIndex; row <= iStartRowIndex; ++row)
                    {
                        for (column = iStartColumnIndex; column <= iEndColumnIndex; column++)
                        {
                            string strColName = sl.GetCellValueAsString(row, column);
                            if (string.IsNullOrWhiteSpace(strColName))
                            {
                                ret.Columns.Add($"Columna{column}");
                            }
                            else
                            {
                                ret.Columns.Add(ret.Columns.Contains(strColName) ?
                                    strColName + "_" + (ret.Columns.Cast<DataColumn>().Where(x => x.ColumnName == strColName).Count() + 1).ToString()
                                    : strColName);
                            }
                        }
                    }
    
                    bool bSeguir = true;
                    int nColumnCodBarras1 = 1;
                    int nColumnCodBarras2 = 27;
    
                    for (row = 2; bSeguir; ++row)
                    {
                        string strCeldaCod1 = sl.GetCellValueAsString(row, nColumnCodBarras1);
                        string strCeldaCod2 = sl.GetCellValueAsString(row, nColumnCodBarras2);
                        if (strCeldaCod1 == strCeldaCod2)
                        {
                            bSeguir = false;
                            continue;
                        }
                        DataRow dataRow = ret.NewRow();
                        colPos = 0;
                        for (column = iStartColumnIndex; column <= iEndColumnIndex; column++)
                        {
                            dataRow[colPos] = sl.GetCellValueAsString(row, column);
                            colPos++;
                        }
                        ret.Rows.Add(dataRow);
                    }
                }
                return ret;
            }

    Este metodo lo que hace es primero lee la primera fila, para obtener el nombre de las columnas, y despues recorre filas hasta que Cod Barras y Nº Prducto sean iguales (esto pasa al estar vacias las 2).

    Con eso, ya tienes en un DataTable el contenido del Excel, pero hay algunos cambios más

    Para el boton de leer:

     private void button1_Click(object sender, EventArgs e)
            {
                string ruta = "";
                string tmp = Application.StartupPath + "\\temp.xlsx";
    
                OpenFileDialog openfile1 = new OpenFileDialog();
                openfile1.Filter = "Excel Files |*.xlsx";
                openfile1.Title = "Seleccione el archivo de Excel";
                if (openfile1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    if (openfile1.FileName.Equals("") == false)
                    {
                        ruta = openfile1.FileName;
                    }
                }
                else
                    return;
    
    
                dt = LeerExcel(ruta, "Hoja1");
    
                DataTable dt1 = GetDataTable();
    
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    if (dt.Rows[i][0].ToString() == "")
                        break;
                    DataRow dr = dt.Rows[i];
                    DataRow newRow = dt1.NewRow();
                    newRow["Codigo"] = dr[0];
                    newRow["Ean"] = dr[1];
                    newRow["Descripcion"] = dr[2];
                    newRow["Cantidad"] = dr[3];
                    newRow["Paquete"] = dr[4];
                    newRow["Neto"] = dr[7];
                    newRow["Importe"] = dr[6];
                    newRow["cantidadleida"] = 0;
                    newRow["pventa"] = 0;
    
    
                    dt1.Rows.Add(newRow);
                }
    
                DataView mifiltro = dt1.DefaultView;
                this.dataGridView1.DataSource = mifiltro;
    
                dataGridView1.Columns[0].HeaderText = "Referencia";
                dataGridView1.Columns[1].HeaderText = "Cod. Barra";
                dataGridView1.Columns[2].HeaderText = "Descipcion";
                dataGridView1.Columns[3].HeaderText = "Cantidad";
                dataGridView1.Columns[4].HeaderText = "Paquete";
                dataGridView1.Columns[5].HeaderText = "Precio Neto";
                dataGridView1.Columns[6].HeaderText = "Precio Total";
    
                dataGridView1.Columns[7].HeaderText = "Cantidad Leida";
                dataGridView1.Columns[8].HeaderText = "Precio Venta";
    
                dataGridView1.Columns[0].ReadOnly = true;
                dataGridView1.Columns[1].ReadOnly = true;
                dataGridView1.Columns[2].ReadOnly = true;
                dataGridView1.Columns[3].ReadOnly = true;
                dataGridView1.Columns[4].ReadOnly = true;
                dataGridView1.Columns[5].ReadOnly = true;
                dataGridView1.Columns[6].ReadOnly = true;
                dataGridView1.Columns[7].ReadOnly = true;
                dataGridView1.Columns[8].ReadOnly = false;
    
    
            }

    Si te fijas, lo unico que he hecho es cambiar el tema del OleDB por el método que hemos añadido.

    Ahora, tenemos que hacer pequeños cambios en el filtrado, ya que algunas columnas han cambiado ligeramente de nombres:

    En 

    var rowcodigo = (from item in dt.Rows.Cast<DataRow>()
                                 let codigo = Convert.ToString(item["Cód# Barras"] == null ? string.Empty : item["Cód# Barras"].ToString())
                                 where codigo == busqueda  //En vez de buscar que contenga, busco que sea igual
                                 select item).FirstOrDefault();

    cambia "Cod# Barras" por "Cód. Barras""

    var rowcodigo = (from item in dt.Rows.Cast<DataRow>()
                                 let codigo = Convert.ToString(item["Cód. Barras"] == null ? string.Empty : item["Cód. Barras"].ToString())
                                 where codigo == busqueda  //En vez de buscar que contenga, busco que sea igual
                                 select item).FirstOrDefault();

    En 

    busqueda = rowcodigo["nº producto1"].ToString();
    strCliente = rowcodigo["Nº cliente"].ToString();

    cambia "nº producto1" por "nº producto_2"

    busqueda = rowcodigo["nº producto_2"].ToString();
    strCliente = rowcodigo["Nº cliente"].ToString();

    y por ultimo, en 

    rowcodigo = (from item in dt.Rows.Cast<DataRow>()
                                     let codigo = Convert.ToString(item["nº producto1"] == null ? string.Empty : item["nº producto1"].ToString())
                                     where codigo == busqueda  //En vez de buscar que contenga, busco que sea igual
                                     select item).FirstOrDefault();

    cambia tambien "nº producto1" por "nº producto_2"

    rowcodigo = (from item in dt.Rows.Cast<DataRow>()
                                     let codigo = Convert.ToString(item["nº producto_2"] == null ? string.Empty : item["nº producto_2"].ToString())
                                     where codigo == busqueda  //En vez de buscar que contenga, busco que sea igual
                                     select item).FirstOrDefault();

    Estos cambios de nombre, se deben a que los nombres los esta cogiendo directamente de la primera fila del Excel, te recomendaria evaluar si convendria que en vez de poner su nombre, utilices su indice, por si el nombre en el excel cambia.

    Los indices son:

    "nº producto_2" -> 26

    "cód barras" -> 27

    "nº cliente" -> 28

    un ejemplo de como se haría es:

    busqueda = rowcodigo[26].ToString();
    strCliente = rowcodigo[28].ToString();

    Con estos cambios, consigues abstraerte totalmente de si los usuarios tienen excel o no, y de la version de excel que tengan, ya que vas a acceder a los excel como si fueran XML, lo malo, es que solo vale para xlsx (2007 en adelante), las versiones anteriores no funcionan.

    La parte buena es esa, que distribuyes las librerias junto a tu ejecutable, y no necesitas en ningun momento tener excel para poder leer los datos, puedes tenerlo o no tenerlo, es irrelevante

    Échale un ojo al código, y nos comentas las dudas. Yo lo he probado con el segundo excel que me pasaste

    Atte


    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:



    viernes, 27 de octubre de 2017 13:33
  • Buenas Rubne,

    Me alegra oir que funciona!!!

    Ahora, tendrás que modificar el instalador para añadir las nuevas dll necesarias, como te decía, usar OpenXML te abstrae de necesitar excel, y solo con las librerías debería funcionar sin problemas, de todos modos, si es posible, verificalo.

    Atte


    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:

    • Marcado como respuesta Ruben Lezcano lunes, 30 de octubre de 2017 11:54
    lunes, 30 de octubre de 2017 10:33

Todas las respuestas

  • Hola

    Primero, el cliente tiene instalado la versión de excel con la que trabaja esta dll y la arquitectura de su procesador es x86 o x64? , un link para ayuda con el error en la dll:

    Solved - The Microsoft.ACE.OLEDB.12.0 provider is not registered on the local machine

    Saludos


    Brayan De la Cruz
    Lima - Perú

    jueves, 26 de octubre de 2017 17:12
  • Hola Brayan no lo se imaginamos si tengo que instalar en 50 equipos no quiero comprobar uno a uno necesito que solo se actualice 

    Saludos


    ruben

    jueves, 26 de octubre de 2017 17:26
  • Buenas Ruben,

    Visto el panorama, quizas podrias evaluar usar librerias que te independicen de Excel y su version

    yo he usado alguna vez esta

    SpreadSheetLight

    Es una libreria basada en OpenXML, y para que se use en cualquier equipo solo tienes que distribuir las dll, asi te evitas el problema de que los clientes no tengan Excel

    Atte


    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:

    jueves, 26 de octubre de 2017 17:40
  • Hola, de acuerdo con los comentarios vertidos anteriormente ,lo primero que te recomendaría es ver si tu proyecto esta compilado en arquitectiura de 64 o 32 , lo mas probable es que este en x64 podrías cambiarlo en las propiedades del proyecto y comprobar si asi funciona en las pc cliente.


    "no quiero comprobar uno a uno necesito que solo se actualice "

    Lo que puedes hacer si insistes en utilizar la arquitectura de 64 en todo caso es que puedes instalar el redistribuilble del OLEDB en cada pc donde se instale tu sistema.

    Microsoft Access Database Engine 2010 Redistributable


    Votar es agradecer.
    Saludos.
    Lima-Per

    jueves, 26 de octubre de 2017 18:54
  • Buenos Días Augusto esta opción no puede ser pues no se cuantos clientes van a instalar y no se que tipo de maquina tendrán ya que van a descargar la aplicación desde Internet

    Saludos


    ruben

    viernes, 27 de octubre de 2017 7:44
  • Hola Jorge como puedo aplicar eso a mi mini proyecto el que me ayudaste a hacerlo

    Saludos


    ruben

    viernes, 27 de octubre de 2017 7:47
  • El error que me da es al leer el archivo 

    app.mpapel.com

    ese es el link


    ruben

    viernes, 27 de octubre de 2017 8:00
  • Jorge no abra otra forma de leer el excel y rellenar el dataggrid

    ruben

    viernes, 27 de octubre de 2017 8:20
  • Buenas Ruben, 

    Ahora mismo no no puedo hacer una prueba porque tengo el proyecto de tu codigo en otro PC, intentare hacerlo a lo largo de el dia de hoy o el fin de semana.

    De todos modos, si miras la documentacion

    SpreadSheetLight

    Hay ejemplos de como leer un excel entero a datatable

    Excel to Datatable (SpreadSheetLight)

    Una vez que tienes el datatable, ya no hay ningun problema, puesto que lo operas igual que lo operarias ahora

    Atte


    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:

    viernes, 27 de octubre de 2017 8:31
  • Vale lo miro cualquier cosa te comento 

    Saludos


    ruben

    viernes, 27 de octubre de 2017 8:58
  • Hola Jorge 

    Estoy probando pero nada no se que hago mal :(

    te paso el codigo de como quedo

    namespace AppcheckMP
    {
    
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
              
                 CadenaConexionSQLServer = "server=80.35.204.5;database=consultaprecios;uid=**;pwd=****;MultipleActiveResultSets=True;";
               }
            string nombreHoja = "Hoja1";
           
            DataTable dt;
            int valor = 0;
            int nLastRow = 0;
            bool bHasPrice = true;
            string strCliente = "";
            string strLastSearch = "";
            #region variables Publicadas
            private string CadenaConexionSQLServer { get; set; }
            #endregion
            private DataView mifiltro = null; //DataView mifiltro
            private DataTable GetDataTable()
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("Codigo");
                dt.Columns.Add("Ean");
                dt.Columns.Add("Descripcion");
                dt.Columns.Add("Cantidad");
                dt.Columns.Add("Paquete");
                dt.Columns.Add("Neto", typeof(decimal));
                dt.Columns.Add("Importe", typeof(decimal));
                dt.Columns.Add("cantidadleida");
                dt.Columns.Add("pventa", typeof(decimal));
    
                return dt;
            }
    
            private void probarconexion()
            {
               
                using (SqlConnection cn = new SqlConnection(CadenaConexionSQLServer))
                {
                    try
                    {
                        cn.Open();
    
                        string queryy = @"SELECT *
                                    FROM consulta ";
                        SqlCommand comando = new SqlCommand(queryy, cn);
                        SqlDataReader reader = comando.ExecuteReader();
                        MessageBox.Show("conexion con Exito");
                        valor = 1;
                    }
                    catch (Exception ex)
                    {
                       // MessageBox.Show("Error" + ex);
                    }
                    cn.Close();
    
                }
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
              // probarconexion();
                textBox1.Focus();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
    
                OleDbConnection conn;
                OleDbDataAdapter MyDataAdapter;
    
                String ruta = "";
                string tmp = Application.StartupPath + "\\temp.xlsx";
                try
                {
                    OpenFileDialog openfile1 = new OpenFileDialog();
                    openfile1.Filter = "Excel Files |*.xlsx";
                    openfile1.Title = "Seleccione el archivo de Excel";
                    if (openfile1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        if (openfile1.FileName.Equals("") == false)
                        {
                            ruta = openfile1.FileName;
                        }
                    }
                    else
                        return;
    
                    if (File.Exists(tmp)) File.Delete(tmp);
                    File.WriteAllBytes(tmp, File.ReadAllBytes(ruta));
    
                    conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;data source=" + tmp + ";Extended Properties='Excel 12.0 Xml;HDR=Yes'");
                    MyDataAdapter = new OleDbDataAdapter("Select * from [" + "Hoja1" + "$]", conn);
                    dt = new DataTable();
                    MyDataAdapter.Fill(dt);
                    
    
    
                    DataTable dt1 = GetDataTable();
    
                    for (int i = 0; i < dt.Rows.Count; i++)
                    {
                        if (dt.Rows[i][0].ToString() == "")
                            break;
                        DataRow dr = dt.Rows[i];
                        DataRow newRow = dt1.NewRow();
                        newRow["Codigo"] = dr[0];
                        newRow["Ean"] = dr[1];
                        newRow["Descripcion"] = dr[2];
                        newRow["Cantidad"] = dr[3];
                        newRow["Paquete"] = dr[4];
                        newRow["Neto"] = dr[7];
                        newRow["Importe"] = dr[6];
                        newRow["cantidadleida"] = 0;
                        newRow["pventa"] = 0;
                     
                     
                        dt1.Rows.Add(newRow);
                    }
                    DataView mifiltro = dt1.DefaultView;
                    this.dataGridView1.DataSource = mifiltro;
                
                    dataGridView1.Columns[0].HeaderText = "Referencia";
                    dataGridView1.Columns[1].HeaderText = "Cod. Barra";
                    dataGridView1.Columns[2].HeaderText = "Descipcion";
                    dataGridView1.Columns[3].HeaderText = "Cantidad";
                    dataGridView1.Columns[4].HeaderText = "Paquete";
                    dataGridView1.Columns[5].HeaderText = "Precio Neto";
                    dataGridView1.Columns[6].HeaderText = "Precio Total";
    
                    dataGridView1.Columns[7].HeaderText = "Cantidad Leida";
                    dataGridView1.Columns[8].HeaderText = "Precio Venta";
    
                    dataGridView1.Columns[0].ReadOnly = true;
                    dataGridView1.Columns[1].ReadOnly = true;
                    dataGridView1.Columns[2].ReadOnly = true;
                    dataGridView1.Columns[3].ReadOnly = true;
                    dataGridView1.Columns[4].ReadOnly = true;
                    dataGridView1.Columns[5].ReadOnly = true;
                    dataGridView1.Columns[6].ReadOnly = true;
                    dataGridView1.Columns[7].ReadOnly = true;
                    dataGridView1.Columns[8].ReadOnly = false;
    
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
    
                textBox1.Focus();
    
                #region Comentarios
                //OleDbConnection conn;
                //OleDbDataAdapter MyDataAdapter;
                //DataTable dt;
                //String ruta = "";
                //try
                //{
                //    OpenFileDialog openfile1 = new OpenFileDialog();
                //    openfile1.Filter = "Excel Files |*.xlsx";
                //    openfile1.Title = "Seleccione el archivo de Excel";
                //    if (openfile1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                //    {
                //        if (openfile1.FileName.Equals("") == false)
                //        {
                //            ruta = openfile1.FileName;
                //        }
                //    }
    
                //    int nRowsSkipear = 33;
                //    conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;data source=" + ruta + ";Extended Properties='Excel 12.0 Xml;HDR=Yes'");
                //    MyDataAdapter = new OleDbDataAdapter("Select * from [" + nombreHoja + "$]", conn);
                //    dt = new DataTable();
                //    MyDataAdapter.Fill(dt);
                //    dt = dt.AsEnumerable().Skip(nRowsSkipear).CopyToDataTable();
    
    
                //    DataTable dDetalle = new DataTable();
                //    DataTable dt1 = GetDataTable();
                //    //MyDataAdapter.Fill(dt);
    
                //    for (int i = 0, k = 0; i < dt.Rows.Count; i++)
                //    {
    
                //        DataRow dr = dt.Rows[i];
                //        DataRow newRow = dt1.NewRow();
                //        newRow["Codigo"] = dr[0];
                //        newRow["Ean"] = dr[1];
                //        newRow["Descripcion"] = dr[2];
                //        newRow["Cantidad"] = dr[3];
                //        newRow["Paquete"] = dr[4];
                //        newRow["Neto"] = dr[5];
                //        newRow["Importe"] = dr[6];
                //        newRow["cantidadleida"] =0;
                //        newRow["pventa"] = 0;
                //        newRow["aa"] = dr[26]; ;
                //        newRow["ab"] = dr[27]; ;
                //        dt1.Rows.Add(newRow);
                //    }
                //    this.mifiltro = dt1.DefaultView;
                //    this.dataGridView1.DataSource = mifiltro;
                //    // dataGridView1.DataSource = dt1;
    
                //    dataGridView1.Columns[0].HeaderText = "Referencia";
                //    dataGridView1.Columns[1].HeaderText = "Cod. Barra";
                //    dataGridView1.Columns[2].HeaderText = "Descipcion";
                //    dataGridView1.Columns[3].HeaderText = "Cantidad";
                //    dataGridView1.Columns[4].HeaderText = "Paquete";
                //    dataGridView1.Columns[5].HeaderText = "Precio Neto";
                //    dataGridView1.Columns[6].HeaderText = "Precio Total";
                //    dataGridView1.Columns[7].HeaderText = "Cantidad Leida";
                //    dataGridView1.Columns[8].HeaderText = "Precio Venta";
    
    
                //int nRowsSkipear = 33;
                //conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;data source=" + ruta + ";Extended Properties='Excel 12.0 Xml;HDR=Yes'");
                //MyDataAdapter = new OleDbDataAdapter("Select F1, F5, F11, F19, F23, F38 from [" + nombreHoja + "$] skip " + nRowsSkipear.ToString(), conn);
                //dt = new DataTable();
                //MyDataAdapter.Fill(dt);
    
                //dataGridView1.DataSource = dt;
                //dataGridView1.DataSource = dt;
    
    
                //for (int i = 0; i < dataGridView1.Columns.Count; i++)
                //{
                //    if (i != 0 && i != 4 && i != 10 && i != 18 && i != 22 && i != 37 )
                //        dataGridView1.Columns[i].Visible = false;
                //    else
                //        dataGridView1.Columns[i].Visible = true;
                //}
                #endregion
    
    
            }
    
            private void textBox1_TextChanged(object sender, EventArgs e)
            {
                if (textBox1.Text == "")
                    return;
          
                string busqueda = textBox1.Text;
                dataGridView1.ClearSelection();
    
    
    
                var rowcodigo = (from item in dt.Rows.Cast<DataRow>()
                                 let codigo = Convert.ToString(item["Cód# Barras"] == null ? string.Empty : item["Cód# Barras"].ToString())
                                 where codigo == busqueda  //En vez de buscar que contenga, busco que sea igual
                                 select item).FirstOrDefault();
                if (rowcodigo == null)
                {
                    busqueda = "";
                    strCliente = "";
                }
                else
                {
                    busqueda = rowcodigo["nº producto1"].ToString();
                    strCliente = rowcodigo["Nº cliente"].ToString();
                }
                if (busqueda == string.Empty)
                {
                    if (textBox1.Text == string.Empty)
                        return;
                    else
                        busqueda = textBox1.Text;
                }
    
    
                List<DataGridViewRow> rows = (from item in dataGridView1.Rows.Cast<DataGridViewRow>()
                                              let codigo = Convert.ToString(item.Cells["Codigo"].Value ?? string.Empty)
                                              let ean = Convert.ToString(item.Cells["Ean"].Value ?? string.Empty)
                                              where codigo == busqueda || //En vez de buscar que contenga, busco que sea igual
                                              ean == busqueda  //En vez de buscar que contenga, busco que sea igual
                                              select item).ToList<DataGridViewRow>();
    
                foreach (DataGridViewRow row in rows)
                {
                    if (row.Index != nLastRow)
                    {
                        if (!bHasPrice)
                        {
                            CustomMessageBox CustomMessage = new CustomMessageBox("El producto no dispone de precio," + (char)13 +" debe introducirlo para continuar!", "Error", 1);
                            CustomMessage.ShowDialog();
                            //MessageBox.Show(null, "El producto no dispone de precio, debe introducirlo para continuar!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                            dataGridView1.Rows[nLastRow].Selected = true;
                            this.dataGridView1.FirstDisplayedScrollingRowIndex = nLastRow;
                            return;
                        }
                       
                    }
                    //En vez de la celda, selecciono la ROW entera   
                    textBox1.Text = ""; //Codigo Ruben
                    row.Selected = true;
                    this.dataGridView1.FirstDisplayedScrollingRowIndex = row.Index;
                    if (string.IsNullOrEmpty(strCliente))
                    {
                        rowcodigo = (from item in dt.Rows.Cast<DataRow>()
                                     let codigo = Convert.ToString(item["nº producto1"] == null ? string.Empty : item["nº producto1"].ToString())
                                     where codigo == busqueda  //En vez de buscar que contenga, busco que sea igual
                                     select item).FirstOrDefault();
                        if (rowcodigo != null)
                            strCliente = rowcodigo["Nº cliente"].ToString();
                    }
           
                }
                foreach (DataGridViewRow row in dataGridView1.SelectedRows)
                {
                    if (row.Cells[0].Value == null)
                        break;
                    int nPrev = 0;
                    int nPaquete = 0;
                    double lfPrecio = 0;
                    int.TryParse(row.Cells["cantidadleida"].Value.ToString(), out nPrev);
                    int.TryParse(row.Cells["cantidad"].Value.ToString(), out nPaquete);
                    double.TryParse(row.Cells["pventa"].Value.ToString(), out lfPrecio);
    
    
                    bHasPrice = lfPrecio > 0;
                    nLastRow = row.Index;
    
                    nPrev += dataGridView1.SelectedRows.Count;
    
                    if (nPrev > nPaquete)
                    {
                        CustomMessageBox CustomMessage = new CustomMessageBox("Va a leer mas de lo comprado," + (char)13 + "desea continuar?", "Advertencia");
    
                        DialogResult res = CustomMessage.ShowDialog();
    
                        if (res != DialogResult.Yes)
                        {
                            return;
                        }
                    }
                    
                    row.Cells["cantidadleida"].Value = nPrev;
                 
    
                }
    
                if (dataGridView1.SelectedRows.Count > 0)
                    textBox1.Text = "";
           
      
            
            }
    
            private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
            {
                if (e.RowIndex == nLastRow)
                {
                    double lfPventa = 0;
                    if (double.TryParse(dataGridView1.Rows[e.RowIndex].Cells["pventa"].Value.ToString(), out lfPventa))
                    {
                        bHasPrice = lfPventa > 0;
                    }
    
                }
            }
    
            private void button3_Click(object sender, EventArgs e)
            {
                double lfPorcentaje = 0;
                double lfNeto = 0;
                if (!double.TryParse(textBox2.Text, out lfPorcentaje))
                {
                    MessageBox.Show("debe introducir un porcentaje valido");
                    return;
                }
    
                foreach (DataGridViewRow row in dataGridView1.Rows)
                {
                    double.TryParse(row.Cells["Neto"].Value.ToString(), out lfNeto);
                    row.Cells["pventa"].Value = ((lfNeto * lfPorcentaje) / 100) + lfNeto;
    
                }
            }
    
            private void btnexportar_Click(object sender, EventArgs e)
            {
                DateTime fecha = DateTime.Today;
                string sql = @"SELECT COUNT(*) 
    					FROM consulta 
    					WHERE cliente = @cliente AND fechacomprobacion = @fecha";
                using (SqlConnection conn = new SqlConnection(CadenaConexionSQLServer))
                {
                    conn.Open();
    
                    SqlCommand cmd = new SqlCommand(sql, conn);
    
                    cmd.Parameters.AddWithValue("@cliente", strCliente);
                    cmd.Parameters.AddWithValue("@fecha", fecha);
    
                    bool bExiste = Convert.ToInt32(cmd.ExecuteScalar()) > 0;
    
                    if (bExiste)
                    {
                        update();
                        //Aqui entrara si existe, pon el codigo del update
                    }
                    else
                    {
                        insertar();
                        //Aqui entrara si no existe, pon el codigo del insert
                    }
                }
    
               
            }
            private void insertar()
            {
                decimal preciocompra = 0;
                DateTime fechahoraguardado = DateTime.Now;
                using (SqlConnection conexion = new SqlConnection(CadenaConexionSQLServer))
                {
                    try
                    {
    
                        SqlCommand insertar = new SqlCommand(@"insert into consulta (referencia, cliente, pcompra, pventa, fechacomprobacion)
                              values(@referencia, @cliente, @pcompra, @pventa, @fechacomprobacion)", conexion);
    
                        conexion.Open();
    
                        foreach (DataGridViewRow fila in dataGridView1.Rows)//SelectedRows)
                        {
                            SqlCommand cmdD = new SqlCommand();
                            SqlConnection ccc = new SqlConnection(CadenaConexionSQLServer);
                            ccc.Open();
                            cmdD.Connection = ccc;
    
    
                            insertar.Parameters.Clear();
                            insertar.Parameters.AddWithValue("@referencia", fila.Cells["codigo"].Value.ToString());
                            insertar.Parameters.AddWithValue("@cliente", strCliente);
    
                            insertar.Parameters.AddWithValue("@pcompra", Convert.ToDecimal(fila.Cells["neto"].Value.ToString()));
                            insertar.Parameters.AddWithValue("@pventa", Convert.ToDecimal(fila.Cells["pventa"].Value.ToString()));
    
                            insertar.Parameters.AddWithValue("@fechacomprobacion", fechahoraguardado);
    
                            insertar.ExecuteNonQuery();
    
                        }
                       // MessageBox.Show("Guardado Correectamente");
                    }
                    catch (SqlException ex)
                    {
    
                        update();
                        // MessageBox.Show("error" + ex);  //(ex.ToString()); //Capturamos el error si existe
                    }
    
                    finally
                    {
    
                        if (conexion.State == ConnectionState.Open) // Finalmente si la conexion esta abierta, la cerramos
                            conexion.Close();
                       // MessageBox.Show("Exportado Correctamente en C:");
    
                    }
    
                }
            }
            private void update()
            {
                using (SqlConnection ccg = new SqlConnection(CadenaConexionSQLServer))
                {
                    string query = @"UPDATE consulta SET pcompra = @pcompra, pventa = @pventa WHERE cliente = @cliente and referencia=@referencia";
    
                    ccg.Open();
    
                  
                    foreach (DataGridViewRow fila1 in dataGridView1.Rows)
                    {
    
    
                        SqlCommand cmd = new SqlCommand(query, ccg);
    
                        cmd.Parameters.AddWithValue("@cliente", strCliente);
                        cmd.Parameters.AddWithValue("@referencia", Convert.ToString(fila1.Cells["codigo"].Value.ToString()));
                        cmd.Parameters.AddWithValue("@pcompra", Convert.ToDecimal(fila1.Cells["neto"].Value.ToString()));
                        cmd.Parameters.AddWithValue("@pventa", Convert.ToDecimal(fila1.Cells["pventa"].Value.ToString()));
                       
                        cmd.ExecuteNonQuery();
                    }
                }
    
            }
            private void exportar ()
            {
    
            }
    
            private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
            {
    
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                this.Close();
            }
        }
    }

    Saludos


    ruben


    viernes, 27 de octubre de 2017 9:28
  • Ruben, 

    Te recomendaría que en cuanto leas este mensaje quites las contraseñas de la cadena de conexión del código que has publicado (salvo que las hayas modificado para que sean falsas).

    Atte 

     


    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:

    viernes, 27 de octubre de 2017 9:55
  • Por otro lado Ruben,

    en el codigo que has puesto, no aparece el uso de SpreadSheetLight por ningun lado.

    Atte


    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:

    viernes, 27 de octubre de 2017 10:44
  • Vale,

    Creo que ya tengo la solucion.

    Lo primero de todo, es que mediante NuGet, añadas los paquetes:

    • DocumentFormat.OpenXml -> Version 2.5.0
    • SpreadsheetLight -> Version 3.4.9

    Una vez que tengas listo eso, añades este using:

    using SpreadsheetLight;

    Ahora, para leer el Excel, vamos a añadir un metodo

    DataTable LeerExcel(string strPath, string strSheet)
            {
                DataTable ret;
                int row;
                int column;
                int colPos = 0;
                using (SLDocument sl = new SLDocument(strPath, strSheet))
                {
                    
                    SLWorksheetStatistics stats = sl.GetWorksheetStatistics();
                    int iStartColumnIndex = stats.StartColumnIndex;
                    int iStartRowIndex = stats.StartRowIndex;
                    int iEndColumnIndex = stats.EndColumnIndex;
                    int iEndRowIndex = stats.EndRowIndex;
    
                    ret = new DataTable("Excel");
    
                    for (row = iStartRowIndex; row <= iStartRowIndex; ++row)
                    {
                        for (column = iStartColumnIndex; column <= iEndColumnIndex; column++)
                        {
                            string strColName = sl.GetCellValueAsString(row, column);
                            if (string.IsNullOrWhiteSpace(strColName))
                            {
                                ret.Columns.Add($"Columna{column}");
                            }
                            else
                            {
                                ret.Columns.Add(ret.Columns.Contains(strColName) ?
                                    strColName + "_" + (ret.Columns.Cast<DataColumn>().Where(x => x.ColumnName == strColName).Count() + 1).ToString()
                                    : strColName);
                            }
                        }
                    }
    
                    bool bSeguir = true;
                    int nColumnCodBarras1 = 1;
                    int nColumnCodBarras2 = 27;
    
                    for (row = 2; bSeguir; ++row)
                    {
                        string strCeldaCod1 = sl.GetCellValueAsString(row, nColumnCodBarras1);
                        string strCeldaCod2 = sl.GetCellValueAsString(row, nColumnCodBarras2);
                        if (strCeldaCod1 == strCeldaCod2)
                        {
                            bSeguir = false;
                            continue;
                        }
                        DataRow dataRow = ret.NewRow();
                        colPos = 0;
                        for (column = iStartColumnIndex; column <= iEndColumnIndex; column++)
                        {
                            dataRow[colPos] = sl.GetCellValueAsString(row, column);
                            colPos++;
                        }
                        ret.Rows.Add(dataRow);
                    }
                }
                return ret;
            }

    Este metodo lo que hace es primero lee la primera fila, para obtener el nombre de las columnas, y despues recorre filas hasta que Cod Barras y Nº Prducto sean iguales (esto pasa al estar vacias las 2).

    Con eso, ya tienes en un DataTable el contenido del Excel, pero hay algunos cambios más

    Para el boton de leer:

     private void button1_Click(object sender, EventArgs e)
            {
                string ruta = "";
                string tmp = Application.StartupPath + "\\temp.xlsx";
    
                OpenFileDialog openfile1 = new OpenFileDialog();
                openfile1.Filter = "Excel Files |*.xlsx";
                openfile1.Title = "Seleccione el archivo de Excel";
                if (openfile1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    if (openfile1.FileName.Equals("") == false)
                    {
                        ruta = openfile1.FileName;
                    }
                }
                else
                    return;
    
    
                dt = LeerExcel(ruta, "Hoja1");
    
                DataTable dt1 = GetDataTable();
    
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    if (dt.Rows[i][0].ToString() == "")
                        break;
                    DataRow dr = dt.Rows[i];
                    DataRow newRow = dt1.NewRow();
                    newRow["Codigo"] = dr[0];
                    newRow["Ean"] = dr[1];
                    newRow["Descripcion"] = dr[2];
                    newRow["Cantidad"] = dr[3];
                    newRow["Paquete"] = dr[4];
                    newRow["Neto"] = dr[7];
                    newRow["Importe"] = dr[6];
                    newRow["cantidadleida"] = 0;
                    newRow["pventa"] = 0;
    
    
                    dt1.Rows.Add(newRow);
                }
    
                DataView mifiltro = dt1.DefaultView;
                this.dataGridView1.DataSource = mifiltro;
    
                dataGridView1.Columns[0].HeaderText = "Referencia";
                dataGridView1.Columns[1].HeaderText = "Cod. Barra";
                dataGridView1.Columns[2].HeaderText = "Descipcion";
                dataGridView1.Columns[3].HeaderText = "Cantidad";
                dataGridView1.Columns[4].HeaderText = "Paquete";
                dataGridView1.Columns[5].HeaderText = "Precio Neto";
                dataGridView1.Columns[6].HeaderText = "Precio Total";
    
                dataGridView1.Columns[7].HeaderText = "Cantidad Leida";
                dataGridView1.Columns[8].HeaderText = "Precio Venta";
    
                dataGridView1.Columns[0].ReadOnly = true;
                dataGridView1.Columns[1].ReadOnly = true;
                dataGridView1.Columns[2].ReadOnly = true;
                dataGridView1.Columns[3].ReadOnly = true;
                dataGridView1.Columns[4].ReadOnly = true;
                dataGridView1.Columns[5].ReadOnly = true;
                dataGridView1.Columns[6].ReadOnly = true;
                dataGridView1.Columns[7].ReadOnly = true;
                dataGridView1.Columns[8].ReadOnly = false;
    
    
            }

    Si te fijas, lo unico que he hecho es cambiar el tema del OleDB por el método que hemos añadido.

    Ahora, tenemos que hacer pequeños cambios en el filtrado, ya que algunas columnas han cambiado ligeramente de nombres:

    En 

    var rowcodigo = (from item in dt.Rows.Cast<DataRow>()
                                 let codigo = Convert.ToString(item["Cód# Barras"] == null ? string.Empty : item["Cód# Barras"].ToString())
                                 where codigo == busqueda  //En vez de buscar que contenga, busco que sea igual
                                 select item).FirstOrDefault();

    cambia "Cod# Barras" por "Cód. Barras""

    var rowcodigo = (from item in dt.Rows.Cast<DataRow>()
                                 let codigo = Convert.ToString(item["Cód. Barras"] == null ? string.Empty : item["Cód. Barras"].ToString())
                                 where codigo == busqueda  //En vez de buscar que contenga, busco que sea igual
                                 select item).FirstOrDefault();

    En 

    busqueda = rowcodigo["nº producto1"].ToString();
    strCliente = rowcodigo["Nº cliente"].ToString();

    cambia "nº producto1" por "nº producto_2"

    busqueda = rowcodigo["nº producto_2"].ToString();
    strCliente = rowcodigo["Nº cliente"].ToString();

    y por ultimo, en 

    rowcodigo = (from item in dt.Rows.Cast<DataRow>()
                                     let codigo = Convert.ToString(item["nº producto1"] == null ? string.Empty : item["nº producto1"].ToString())
                                     where codigo == busqueda  //En vez de buscar que contenga, busco que sea igual
                                     select item).FirstOrDefault();

    cambia tambien "nº producto1" por "nº producto_2"

    rowcodigo = (from item in dt.Rows.Cast<DataRow>()
                                     let codigo = Convert.ToString(item["nº producto_2"] == null ? string.Empty : item["nº producto_2"].ToString())
                                     where codigo == busqueda  //En vez de buscar que contenga, busco que sea igual
                                     select item).FirstOrDefault();

    Estos cambios de nombre, se deben a que los nombres los esta cogiendo directamente de la primera fila del Excel, te recomendaria evaluar si convendria que en vez de poner su nombre, utilices su indice, por si el nombre en el excel cambia.

    Los indices son:

    "nº producto_2" -> 26

    "cód barras" -> 27

    "nº cliente" -> 28

    un ejemplo de como se haría es:

    busqueda = rowcodigo[26].ToString();
    strCliente = rowcodigo[28].ToString();

    Con estos cambios, consigues abstraerte totalmente de si los usuarios tienen excel o no, y de la version de excel que tengan, ya que vas a acceder a los excel como si fueran XML, lo malo, es que solo vale para xlsx (2007 en adelante), las versiones anteriores no funcionan.

    La parte buena es esa, que distribuyes las librerias junto a tu ejecutable, y no necesitas en ningun momento tener excel para poder leer los datos, puedes tenerlo o no tenerlo, es irrelevante

    Échale un ojo al código, y nos comentas las dudas. Yo lo he probado con el segundo excel que me pasaste

    Atte


    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:



    viernes, 27 de octubre de 2017 13:33
  • Llevas Razon es de prueba :)   pero lo tengo en cuenta

    Saludos


    ruben

    viernes, 27 de octubre de 2017 14:08
  • Eres un genio funciona a la perfección

    Saludos


    ruben

    lunes, 30 de octubre de 2017 10:17
  • Buenas Rubne,

    Me alegra oir que funciona!!!

    Ahora, tendrás que modificar el instalador para añadir las nuevas dll necesarias, como te decía, usar OpenXML te abstrae de necesitar excel, y solo con las librerías debería funcionar sin problemas, de todos modos, si es posible, verificalo.

    Atte


    No olvides votar mi comentario si te ha ayudado y marcarlo como respuesta si ha sido la solución, con eso ayudas a mejorar mi reputación en la comunidad y a identificar la respuesta a la gente que tenga el mismo problema.

    Para obtener una respuesta lo más rápida y concisa posible, te recomiendo:

    • Marcado como respuesta Ruben Lezcano lunes, 30 de octubre de 2017 11:54
    lunes, 30 de octubre de 2017 10:33
  • Estoy probando en una tablet microsoft y funciona de momento

    Saludos


    ruben

    lunes, 30 de octubre de 2017 11:54