Database Excel (no sql) advanced datagrid view - Autofilter

di
Anonimizzato28652
il
5 risposte

Database Excel (no sql) advanced datagrid view - Autofilter

Buonasera a tutti.
Ho creato su excel una lista di file sotto forma di database/tabella dove ho indicato varie informazioni (Autore, titolo, argomenti trattati etc). Nell'ultima colonna ho poi concatenato tutte le stringhe precendenti in un'unica stringa.

Ho poi creato una interfaccia in C# che mi carica la tabella del file excel in un DataGridView (io ho usato la risorsa esterna advancedDataGridView). ----> questo primo passo l'ho fatto.

Adesso vorrei inserire una texbox di ricerca dove inserendo del testo, in tempo reale, il DataGridView viene filtrato (usando come riferimento l'ultima colonna che contiene tutti i dati) mostrandomi tutte le righe in cui è presente il testo cercato.

vi posto il codice di seguito. (Sono nuovo del C# mi piace smanettarci e capire come funziona per crearmi degli strumenti utili per il mio lavoro senza aver la presunzione di diventare un programmatore avanzato, per cui perdonatemi se certe istruzioni sono rudimentali e poco "eleganti")

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Office.Interop.Excel;
using Zuby.ADGV;

namespace ARCHIVIO_1._0
{
    public partial class DATABASE : Form
    {

        Microsoft.Office.Interop.Excel.Application App;
        Microsoft.Office.Interop.Excel.Workbook wb;
        Microsoft.Office.Interop.Excel.Worksheet ws;
        Microsoft.Office.Interop.Excel.Range Range;

        public DATABASE()
        {
            InitializeComponent();
            
            int n;

            string Path = Directory.GetCurrentDirectory();
            string strfileName;
            strfileName = Convert.ToString(Path + @"\ARCHIVIO.xlsm");

            //Check if database_file.xlsx exists
            if (File.Exists(strfileName))
            {
                n = 1;
            }
            else
            {
                MessageBox.Show("Il database non è presente nella directory corrente.\n" + "Il database non è stato caricato.");
                openFileDialog1.Filter = "Excel Office | *.xls; *.xlsx; *.xlsm";
                openFileDialog1.ShowDialog();
                strfileName = openFileDialog1.FileName;
            }

            if (strfileName != string.Empty)
            {
                App = new Microsoft.Office.Interop.Excel.Application();
                wb = App.Workbooks.Open(strfileName);
                ws = wb.Worksheets["ARCHIVIO"];
                Range = ws.UsedRange;

                int i = 0;
                int Row;
                
                for (Row = 8; Row <= Range.Rows.Count; Row++)
                {
                    if (Range.Cells[Row, 3].Text != "")
                    {
                        i++;
                        advancedDataGridView.Rows.Add(i, Range.Cells[Row, 4].Text,
                                                            			Range.Cells[Row, 5].Text,
                                                            			Range.Cells[Row, 6].Text,
                                                           			Range.Cells[Row, 7].Text,
                                                            			Range.Cells[Row, 8].Text,
                                                            			Range.Cells[Row, 9].Text,
                                                            			Range.Cells[Row, 10].Text,
                                                            			Range.Cells[Row, 11].Text,
                                                            			Range.Cells[Row, 12].Text,
                                                            			Range.Cells[Row, 13].Text,
                                                            			Range.Cells[Row, 14].Text,
                                                            			Range.Cells[Row, 15].Text,
                                                            			Range.Cells[Row, 16].Text,
                                                            			Range.Cells[Row, 14].Text);
                    }   //end if
                    else
                    {
                        //Nothing
                    }
                    num_record.Text = Convert.ToString("Record : " + Row);
                }   //end for
            }   //end if
            else
            {
                //Nothing
            }
        } //end form1

        private void Ctrl_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                this.SelectNextControl((Control)sender, true, true, true, true);                   //Select next control
            }
            else
            {

            }
        }
    }
}


Ho provato con questo ma senza risultato

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            BindingSource bs = new BindingSource();
            bs.DataSource = advancedDataGridView.DataSource;
            bs.Filter = advancedDataGridView.Columns[14].HeaderText.ToString() + "*" + textBox1.Text + "*";
            advancedDataGridView.DataSource = bs;
        }

5 Risposte

  • Re: Database Excel (no sql) advanced datagrid view - Autofilter

    Ciao,
    secondo me il codice che hai inserito nell'evento TextChanged non funziona perché fai il giro
    bs.DataSource = DataGridView.DataSource
    e quindi
    DataGridView.DataSource => bs
    praticamente li incroci (scusa il termine poco informatico).

    Io farei in questo modo:
    1) Creo un oggetto DataTable che è semplicemente una tabella per contenere in memoria i dati caricati;
    2) Popolo il DataTable con i dati letti dal file excel;
    3) Creo un BindingSource e gli associo il DataTable;
    4) Associo il BindingSource al DataGridView;
    Poi:
    5) Nell'evento TextChanged definisco la proprietà Filter del BindingSource (che va a leggersi il testo nel TextBox);
    6) Faccio il refresh del DataGridView.
    
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using Microsoft.Office.Interop.Excel;
    
    namespace WinformCs
    {
        public partial class FrmExcel : Form
        {
            Microsoft.Office.Interop.Excel.Application App;
            Microsoft.Office.Interop.Excel.Workbook wb;
            Microsoft.Office.Interop.Excel.Worksheet ws;
            Microsoft.Office.Interop.Excel.Range Range;
    
            BindingSource bs = new BindingSource();
    
            public FrmExcel()
            {
                InitializeComponent();
            } 
    
            private void FrmExcel_Load(object sender, EventArgs e)
            {
                int n;
    
                //Create datatable with one column
                System.Data.DataTable dt = new System.Data.DataTable();
                DataColumn dataColumn = new DataColumn("nomi", System.Type.GetType("System.String"));
                dt.Columns.Add(dataColumn);
    
                //string Path = Directory.GetCurrentDirectory();
                string strfileName;
                strfileName = Convert.ToString(@"C:\Users\Luciano\Desktop\prova.xlsx");
    
                //Check if database_file.xlsx exists
                if (File.Exists(strfileName))
                {
                    n = 1;
                }
                else
                {
                    //MessageBox.Show("Il database non è presente nella directory corrente.\n" + "Il database non è stato caricato.");
                    //openFileDialog1.Filter = "Excel Office | *.xls; *.xlsx; *.xlsm";
                    //openFileDialog1.ShowDialog();
                    //strfileName = openFileDialog1.FileName;
                }
    
                if (strfileName != string.Empty)
                {
                    App = new Microsoft.Office.Interop.Excel.Application();
                    wb = App.Workbooks.Open(strfileName);
                    ws = wb.Worksheets["Foglio1"];
                    Range = ws.UsedRange;                
    
                    int i = 0;
                    int Row;
    
                    for (Row = 2; Row <= Range.Rows.Count; Row++)
                    {
                        if (Range.Cells[Row, 1].Text != "")
                        {
                            i++;
                            dt.Rows.Add(Range.Cells[Row, 1].Text);                        
                        }
                        else
                        {
                            //Nothing
                        }
                        //num_record.Text = Convert.ToString("Record : " + Row);
                    }   //end for
    
                    
                }   //end if
                else
                {
                    //Nothing
                }
    
                bs.DataSource = dt;
                dataGridView1.DataSource = bs;
            }       
    
            private void textBox1_TextChanged(object sender, EventArgs e)
            {
                bs.Filter = "nomi = '" + textBox1.Text + "'";
                dataGridView1.Refresh();
            }
        }
    }
    
    Note:
    1) Ho fatto delle modifiche per poter provare il tuo codice con un mio file excel di prova;
    2) Ho utilizzato un DataGridView normale, ma non dovrebbe cambiare nulla;
    3) Nel costruttore di solito non andrebbe inserito codice, è preferibile sfruttare il metodo Load del Form.

    Lucius
  • Re: Database Excel (no sql) advanced datagrid view - Autofilter

    Intanto ti ringrazio per la velocissima risposta! non mi aspettavo tale rapidità.
    Adesso mi studio bene il codice che hai postato. Il motivo di aver usato l'advanced grid view deriva dal fatto che voglio eseguire una ricerca in tempo reale senza dover poi clicare altri tasti.

    In pratica se ho ad esempio questo elenco :

    1 - Appunti - Verifiche di stabilità di un pendio.pdf
    2 - Appunti - Verifiche di stabilità muri di sostegno e stabilità globale.pdf
    3 - Appunti - Verifiche geotecniche.pdf
    4 - AZTEC - CARL - Carico limite e cedimenti.pdf
    5 - AZTEC - CARL - Carico limite.pdf
    6 - AZTEC - MAX - Analisi e calcolo muri di sostegno.pdf

    vorrei digitare nella textbox "di" e avere istantaneamente l'elenco filtrato ---> mi verrebbero esclusi il 3 e il 5 record

    se però aggiungessi adesso "dim" avrei come risultato solo il 4 record "ceDIMenti"

    E cercando in rete mi è sembrato di capire che il DGV normale non faccia questa operazione mentre ho visto che l'advanced dovrebbe farlo (oltre ad avere le classiche possibilità di filtraggio presente nel filtro dati di excel). Il problema è che tutte le risorse che ho trovato si appoggiano a database veri e propri... ma nel mio caso è più pratico appoggiarmi a un documento excel che posso anche modificare direttamente con formule etc.

    Ti chiedo una cosa, secondo te è possibile con DGV o con ADGV inserire dei link diretti ai pdf dell'elenco? così da aprire direttamente il file una volta cercato? E' inoltre possibile gestire le formule di excel?

    Grazie, vado a studiare il tuo codice
  • Re: Database Excel (no sql) advanced datagrid view - Autofilter

    Allora ho modificato il mio codice secondo le tue indicazioni.
    Sono riuscito a creare il DataTable e sono riuscito a popolarlo con i dati presenti nel mio archivio. L'unica colonna che non mi carica è l'ultima e non so perchè...
    Su excel è il risultato di questa formula "=+CONCATENA([@CATEGORY];"-";[@[NAME FILE]];"-";[@[KEY WORDS]])". Magari non funziona per questo motivo. Altre colonne sono il risultato di un concatena ma non in forma "matriciale".

    La ricerca più o meno funziona ma solo per la prima colonna ID: se scrivo "3" mi trova la riga 3, ma non per dire la colonna 13 o la 33 o la 131 e così via.
    Inoltre una volta cancellato il testo nella textbox, il datatable si svuota e non torna alla visualizzazione di default.

    Tuttavia io vorrei cercare proprio nella collonna FILTRO DI RICERCA che contiene tutte le parole utili a farmi trovare il file che sto cercando.
    Ho quindi provato a scrivere ma mi restituisce l'errore
    
    private void textBox1_TextChanged(object sender, EventArgs e)
            {
                bs.Filter = "FILTRO DI RICERCA = '" + textBox1.Text + "'";
                advancedDataGridView.Refresh();
            }
    
    CODICE COMPLETO
    
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using Microsoft.Office.Interop.Excel;
    using NPOI.SS.UserModel;
    using Zuby.ADGV;
    
    namespace ARCHIVIO_1._0
    {
        public partial class DATABASE : Form
        {
    
            Microsoft.Office.Interop.Excel.Application App;
            Microsoft.Office.Interop.Excel.Workbook wb;
            Microsoft.Office.Interop.Excel.Worksheet ws;
            Microsoft.Office.Interop.Excel.Range Range;
            Microsoft.Office.Interop.Excel.DataTable dt;
    
            BindingSource bs = new BindingSource();
    
            public DATABASE()
            {
                InitializeComponent();
    
                int n;
    
                //Create datatable
                System.Data.DataTable dt = new System.Data.DataTable();
                
                DataColumn dataColumn1 = new DataColumn("ID", System.Type.GetType("System.String"));
                DataColumn dataColumn2 = new DataColumn("LINK", System.Type.GetType("System.String"));
                DataColumn dataColumn3 = new DataColumn("CATEGORY", System.Type.GetType("System.String"));
                DataColumn dataColumn4 = new DataColumn("NAME FILE", System.Type.GetType("System.String"));
                DataColumn dataColumn5 = new DataColumn("KEY WORDS", System.Type.GetType("System.String"));
                DataColumn dataColumn6 = new DataColumn("PERCORSO COMPLETO", System.Type.GetType("System.String"));
                DataColumn dataColumn7 = new DataColumn("APPUNTI", System.Type.GetType("System.String"));
                DataColumn dataColumn8 = new DataColumn("SUB 1", System.Type.GetType("System.String"));
                DataColumn dataColumn9 = new DataColumn("SUB 2", System.Type.GetType("System.String"));
                DataColumn dataColumn10 = new DataColumn("ESTENSIONE", System.Type.GetType("System.String"));
                DataColumn dataColumn11 = new DataColumn("AUTORE", System.Type.GetType("System.String"));
                DataColumn dataColumn12 = new DataColumn("TITOLO", System.Type.GetType("System.String"));
                DataColumn dataColumn13 = new DataColumn("SITO", System.Type.GetType("System.String"));
                DataColumn dataColumn14 = new DataColumn("FILTRO DI RICERCA", System.Type.GetType("System.String"));
    
                dt.Columns.Add(dataColumn1);
                dt.Columns.Add(dataColumn2);
                dt.Columns.Add(dataColumn3);
                dt.Columns.Add(dataColumn4);
                dt.Columns.Add(dataColumn5);
                dt.Columns.Add(dataColumn6);
                dt.Columns.Add(dataColumn7);
                dt.Columns.Add(dataColumn8);
                dt.Columns.Add(dataColumn9);
                dt.Columns.Add(dataColumn10);
                dt.Columns.Add(dataColumn11);
                dt.Columns.Add(dataColumn12);
                dt.Columns.Add(dataColumn13);
                dt.Columns.Add(dataColumn14);
    
                //Load database_file excel
                string Path = Directory.GetCurrentDirectory();
                string strfileName;
                strfileName = Convert.ToString(Path + @"\ARCHIVIO.xlsm");
    
                //Check if database file exists
                if (File.Exists(strfileName))
                {
                    n = 1;
                }
                else
                {
                    MessageBox.Show("Il database non è presente nella directory corrente.\n" + "Il database non è stato caricato.");
                    openFileDialog1.Filter = "Excel Office | *.xls; *.xlsx; *.xlsm";
                    openFileDialog1.ShowDialog();
                    strfileName = openFileDialog1.FileName;
                }
    
                if (strfileName != string.Empty)
                {
                    App = new Microsoft.Office.Interop.Excel.Application();
                    wb = App.Workbooks.Open(strfileName);
                    ws = wb.Worksheets["ARCHIVIO"];
                    Range = ws.UsedRange;
                    
                    int i = 0;
                    int Row;
                    for (Row = 8; Row <= Range.Rows.Count; Row++)
                    {
                        if (Range.Cells[Row, 3].Text != "")
                        {
                            i++;
                            dt.Rows.Add(i, Range.Cells[Row, 4].Text,
                                            Range.Cells[Row, 5].Text,
                                            Range.Cells[Row, 6].Text,
                                            Range.Cells[Row, 7].Text,
                                            Range.Cells[Row, 8].Text,
                                            Range.Cells[Row, 9].Text,
                                            Range.Cells[Row, 10].Text,
                                            Range.Cells[Row, 11].Text,
                                            Range.Cells[Row, 12].Text,
                                            Range.Cells[Row, 13].Text,
                                            Range.Cells[Row, 14].Text);
                        }   //end if
                        else
                        {
                            //Nothing
                        }
                        num_record.Text = Convert.ToString("Record : " + i);
                    }   //end for
                }   //end if
                else
                {
                    //Nothing
                }
    
                bs.DataSource = dt;
                advancedDataGridView.DataSource = bs;
    
            } //end form1
    
    private void textBox1_TextChanged(object sender, EventArgs e)
            {
                bs.Filter = "ID = '" + textBox1.Text + "'";
                advancedDataGridView.Refresh();
            }
            
    
  • Re: Database Excel (no sql) advanced datagrid view - Autofilter

    Scusami ma sono un po' preso con un nuovo problema.

    1) Premesso che non conosco Adgv, non l'ho mai usato, per aprire un file puoi gestire l'evento DataGridView.CellClick del Dgv
    vedi: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.datagridview.cellclick?view=net-5.0
    In questo modo ti puoi prendere il valore della cella che contiene il nome del file, e per aprirlo puoi utilizzare il metodo Process.Start()
    vedi: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.process.start?view=net-5.0
    che permette di lanciare il file Excel dando solo il nome del file. Att.ne non ricordo bene ma penso che vada indicato il percorso completo del file es: C:\users\luciano\desktop...

    2) Quando cancelli la casella di ricerca per far ricomparire tutta la lista dei file:
    A) o richiami il metodo RemoveFilter() dell'oggetto BindingSource per rimuovere il filtro;
    B) richiami la routine di ricerca dei file (a questo punto sarebbe meglio secondo me spostare tutto il codice della routine di ricerca in un metodo a parte e richiamarlo sia dal metodo Load() cioè quello che viene eseguito al caricamento del form, sia dall'evento TextChanged() del TextBox.
    In pratica fai un IF, se la proprietà Text del TextBox è vuota richiami l'evento di ricarica della lista file (punto B) o rimuovi il filtro come (punto A).

    3) Per impostare un filtro avanzato nel BindingSource bisogna utilizzare il LIKE come in Sql per trovare tutte le occorrenze che contengono il valore passato
    vedi: https://arsalantamiz.blogspot.com/2008/05/filtering-data-using-bindingsource.html
    Lucius
  • Re: Database Excel (no sql) advanced datagrid view - Autofilter

    Figurati, ci mancherebbe, anzi grazie per le preziose informazioni.

    Ho quindi utilizzato il dgw normale,ho utilizzato il "LIKE" e sfruttato la funzione RemoveFilter() risolvendo tutti i problemi di filtraggio.
    Riguardando il codice mi sono anche accorto che creavo una tabella di 14 colonne ma ne caricavo 11 Quindi ho anche risolto il problema delle ultime due colonne non caricate (nel file excel la tabella inizia dalla cella C8 e quindi sfalsando gli indici delle colonne mi sono perso le ultime 2).

    Detto ciò ho quindi risolto la parte di caricamento dei dati dell'excel e di filtraggio. A orari più consoni vedrò gli eventi che mi hai consigliato per l'apertura dei file...

    Grazie ancora!
Devi accedere o registrarti per scrivere nel forum
5 risposte