none
DataGridView Excel ReadOnly

    Frage

  • Hallo zusammen,

    ich befülle ein DGV mit Hilfe des OLEDB,
    oft kommt es vor, dass wenn ein User mein Tool startet ein Fehler erscheint, da die Exceltabelle im Hintergrund durch einen anderen
    User "exclusiv geöffnet" ist.
    Ich habe nun in Google gefunden, dass es bei den "Extendet Properties" ein Befehl "ReadOnly" gibt, das funktioniert aber leider nicht.
    Wie kann ich das dennoch irgendwie erreichen, dass die Exceltabelle nur im "LesenModus" geöffnet wird, das DGV gefüllt wird, und wieder geschlossen wird, ohne dass sich die Usere gegenseitig blockieren?

    Danke.

    Gruß Frank

    try   
    {                
    var excelFile = verbindung_zu_definitionen.getPfad();
    var hdr = "Yes";                    //hasHeaders ? "Yes" : "No";                
    var binding_excel = new BindingSource();                
    string connectionString;                //Prüfen welches Excel OLEDB geladen werden soll                                          
    if (excelFile.Substring(excelFile.LastIndexOf('.')).ToLower() == ".xlsx")
    {
             connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFile + 
             ";Extended Properties=\"Excel 12.0 Xml;HDR=" + hdr + ";IMEX=1;READONLY=TRUE\"";                 
    }
    else                    
    {
    	 connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + excelFile +                                
    	 ";Extended Properties=\"Excel 8.0;HDR=" + hdr + ";IMEX=1;READONLY=TRUE\"";                //Alle Spalten von Tabelle1 lesen                
    }
    var adapter = new OleDbDataAdapter("SELECT * FROM [CM$]", connectionString);                
    //Verbindung zur Tabelle aufbauen                
    var ds = new DataSet();                                               
    //Zu lesende Tabelle angeben                
    adapter.Fill(ds, "CM");                
    //Tabelle auswählen                
    dt_filter = ds.Tables["CM"];                
    //Binden da DataGridViewAutoFilter nur mit einem Binding arbeiten                
    binding_excel.DataSource = dt_filter;                
    //Mit DGV verknüpfen                
    dGvexcel.DataSource = binding_excel;	//Daten mit dem DGV verknüpfen            
    }



    Mittwoch, 14. Februar 2018 07:53

Antworten

  • HI,
    Excel ist ein Ein-Platz-System. Bei zeitgleichen Zugriff auf eine Excel-Datei kann es auf dem Niveau des Betriebssystem zu Blockierungen kommen. Für die Lösung Deines Problems gibt es verschiedenen Möglichkeiten: SQL Server anstelle Excel, Kopie der Excel-Datei auf Betriebssystem-Ebene, Zwischen-Proxy wie beispielsweise ein WebService, der den Mehrfachzugriff ermöglicht.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Mittwoch, 14. Februar 2018 09:04
  • Hallo Stefan,

    ok danke für den Tipp, das "Dispose" habe ich nun eingebaut, und habe nun eine Abfrage erstellt, ob das Excel in Verwendung ist, sieht dann so aus:

    if (eingabe_kontrolle.IsFileLocked(verbindung_zu_definitionen.getPfad()) == false) //wenn Datei nicht in Nutzung
    {                
    	try                
    	{                    
    		var excelFile = verbindung_zu_definitionen.getPfad();                    
    		var hdr = "Yes";                    //hasHeaders ? "Yes" : "No";                    
    		var binding_excel = new BindingSource();                    
    		string connectionString;                    //Prüfen welches Excel OLEDB geladen werden soll                           
    
                        if (excelFile.Substring(excelFile.LastIndexOf('.')).ToLower() == ".xlsx")
                        {
                            connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFile +
                                               ";Extended Properties=\"Excel 12.0 Xml;HDR=" + hdr + ";IMEX=1\"";        //; READONLY=TRUE\"";   funktioniert nicht
                        }
                        else
                        {
                            connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + excelFile +
                                        ";Extended Properties=\"Excel 8.0;HDR=" + hdr + ";IMEX=1\"";                    //; READONLY=TRUE\"";   funktioniert nicht
                        }
                        //Alle Spalten von Tabelle1 lesen
                        var adapter = new OleDbDataAdapter("SELECT * FROM [CM$]", connectionString);
                        //Verbindung zur Tabelle aufbauen
                        var ds = new DataSet();
                        //Zu lesende Tabelle angeben
                        adapter.Fill(ds, "CM");
                        //Tabelle auswählen
                        dt_filter = ds.Tables["CM"];
                        //Binden da DataGridViewAutoFilter nur mit einem Binding arbeiten
                        binding_excel.DataSource = dt_filter;
                        //Mit DGV verknüpfen
                        dGvexcel.DataSource = binding_excel;	//Daten mit dem DGV verknüpfen
                        //Adapter entsorgen /  freigeben
                        adapter.Dispose();
                    }
    }            
    else
                {
                    DialogResult frage = MessageBox.Show("Fehler beim abrufen des Arbeitsvorrats!\nDie Datei ist von einem anderen Benutzer in Arbeit.\n\n" +
                                                                        "Wollen Sie den Vorgang wiederholen?\n\n" +
                                                                        "(Sollte der Fehler häufiger vorkommen, wenden Sie sich an\n" + verbindung_zu_definitionen.get_fehler_email_adresse() + ")", "Fehler beim abrufen!!", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                    if (frage == DialogResult.Yes)
                    {
                        dgv_fuellen();              //Versuch Excel nochmal zu laden
                    }
                    else
                     {
                        maske_reset();
                        Close();
                        Application.Exit();
                    }
                }
    ...
    
    Abfrage Methode:
    
     public bool IsFileLocked(string pfad)
            {            FileStream stream = null;
                try
                {
                    stream = File.Open(pfad,FileMode.Open, FileAccess.Read, FileShare.None);                //file is not locked
                    return false;
                }
                catch (IOException)
                {
                    return true;
                }
                finally
                {
                    if (stream != null)
                        stream.Close();
                }
            }

    Scheint zu funktionieren wie ich es will :)

    Gruß Frank

    • Als Antwort markiert Edzio33 Donnerstag, 15. Februar 2018 11:26
    Mittwoch, 14. Februar 2018 12:08

Alle Antworten

  • HI,
    Excel ist ein Ein-Platz-System. Bei zeitgleichen Zugriff auf eine Excel-Datei kann es auf dem Niveau des Betriebssystem zu Blockierungen kommen. Für die Lösung Deines Problems gibt es verschiedenen Möglichkeiten: SQL Server anstelle Excel, Kopie der Excel-Datei auf Betriebssystem-Ebene, Zwischen-Proxy wie beispielsweise ein WebService, der den Mehrfachzugriff ermöglicht.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Mittwoch, 14. Februar 2018 09:04
  • Hallo Peter,

    danke für die Antwort.

    Also geht das nicht mit dem

    ;READONLY=TRUE\""; 

    so dass nur gelesen wird, bzw. dann ist die Exceldatei dennoch "belegt".

    Hatte gedacht, dass mit dem DataSource und Binding die Excel entkoppelt wird :-)

    Gruß Frank

    Mittwoch, 14. Februar 2018 09:24
  • Hallo Frank,

    wenn die Exceldatei durch einen anderen Prozess (sei es Excel selbst oder irgendeine andere Anwendung, die die Exceldatei offen hält) verwendet wird, ist diese dann exklusiv geöffnet und Du kannst die in der Regel auch nicht mehr zum Lesen öffnen.

    Da deine Anwendung eine Connection öffnet, diese aber nicht mehr schließt, dürfte das die Ursache sein.

    Entsorge den OleDbDataAdapter nach dem Lesen über:

    adapter.Dispose();

    Dann sollte diese Ursache zumindest nicht mehr bestehen.

     


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community


    Mittwoch, 14. Februar 2018 09:33
    Moderator
  • Hallo Stefan,

    ok danke für den Tipp, das "Dispose" habe ich nun eingebaut, und habe nun eine Abfrage erstellt, ob das Excel in Verwendung ist, sieht dann so aus:

    if (eingabe_kontrolle.IsFileLocked(verbindung_zu_definitionen.getPfad()) == false) //wenn Datei nicht in Nutzung
    {                
    	try                
    	{                    
    		var excelFile = verbindung_zu_definitionen.getPfad();                    
    		var hdr = "Yes";                    //hasHeaders ? "Yes" : "No";                    
    		var binding_excel = new BindingSource();                    
    		string connectionString;                    //Prüfen welches Excel OLEDB geladen werden soll                           
    
                        if (excelFile.Substring(excelFile.LastIndexOf('.')).ToLower() == ".xlsx")
                        {
                            connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + excelFile +
                                               ";Extended Properties=\"Excel 12.0 Xml;HDR=" + hdr + ";IMEX=1\"";        //; READONLY=TRUE\"";   funktioniert nicht
                        }
                        else
                        {
                            connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + excelFile +
                                        ";Extended Properties=\"Excel 8.0;HDR=" + hdr + ";IMEX=1\"";                    //; READONLY=TRUE\"";   funktioniert nicht
                        }
                        //Alle Spalten von Tabelle1 lesen
                        var adapter = new OleDbDataAdapter("SELECT * FROM [CM$]", connectionString);
                        //Verbindung zur Tabelle aufbauen
                        var ds = new DataSet();
                        //Zu lesende Tabelle angeben
                        adapter.Fill(ds, "CM");
                        //Tabelle auswählen
                        dt_filter = ds.Tables["CM"];
                        //Binden da DataGridViewAutoFilter nur mit einem Binding arbeiten
                        binding_excel.DataSource = dt_filter;
                        //Mit DGV verknüpfen
                        dGvexcel.DataSource = binding_excel;	//Daten mit dem DGV verknüpfen
                        //Adapter entsorgen /  freigeben
                        adapter.Dispose();
                    }
    }            
    else
                {
                    DialogResult frage = MessageBox.Show("Fehler beim abrufen des Arbeitsvorrats!\nDie Datei ist von einem anderen Benutzer in Arbeit.\n\n" +
                                                                        "Wollen Sie den Vorgang wiederholen?\n\n" +
                                                                        "(Sollte der Fehler häufiger vorkommen, wenden Sie sich an\n" + verbindung_zu_definitionen.get_fehler_email_adresse() + ")", "Fehler beim abrufen!!", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                    if (frage == DialogResult.Yes)
                    {
                        dgv_fuellen();              //Versuch Excel nochmal zu laden
                    }
                    else
                     {
                        maske_reset();
                        Close();
                        Application.Exit();
                    }
                }
    ...
    
    Abfrage Methode:
    
     public bool IsFileLocked(string pfad)
            {            FileStream stream = null;
                try
                {
                    stream = File.Open(pfad,FileMode.Open, FileAccess.Read, FileShare.None);                //file is not locked
                    return false;
                }
                catch (IOException)
                {
                    return true;
                }
                finally
                {
                    if (stream != null)
                        stream.Close();
                }
            }

    Scheint zu funktionieren wie ich es will :)

    Gruß Frank

    • Als Antwort markiert Edzio33 Donnerstag, 15. Februar 2018 11:26
    Mittwoch, 14. Februar 2018 12:08