none
c# oledb et excel RRS feed

  • Question

  • Bonjour,

    je ne suis pas sur d'être sur le bon forum, merci d'avance pour votre indulgence.

    J'essaie de connaitre le nombre de colonnes d'une feuille excel (pour essayer d'optimiser un une requête OLEDB select * from [Feuil1$]).

    Je fais donc un select * from [Feuil1$1:1] pour pouvoir faire un OleDataReader.FieldCount.

    Sauf que select * from [Feuil1$], select * from [Feuil1$1:1] même combat, il me charge les 350 000 lignes du fichier excel en mémoire <=> 4Go pour un fichier de 400Mo.

    J'obtient bien in fine une requête select * from [Feuil1$A:GY], mais je n'ai rien optimisé du tout...

    Est-il possible de ne charger (via oledb) que la première ligne de la feuille excel ?

     

    Questions annexes:

    - dois-je rennoncer à oledb pour excel ?

    - adapter le fournisseur pour qu'il me renvoie des pages de lignes et ainsi éviter ce "gavage" de mémoire ?


    thierry
    lundi 19 décembre 2011 16:06

Réponses

  • Dans ce cas si votre fichier excel est récent (2007 et + ) vous pourriez envisager d'utiliser l'API Open Xml au lieu du driver OleDb. Avec cet API, il est possible de lire le fichier soit en parsant tout le document (DOM) ou élément par élément (SAX).

    Dans votre cas l'approche SAX éviterait de charger tout le document : vous trouverez un exemple des 2 approches ici :

    How to: Parse and Read a Large Spreadsheet Document

    Cordialement

     

    lundi 19 décembre 2011 17:24
    Modérateur

Toutes les réponses

  • Bonjour,

    Essayer : select top 1 * from [Feuil1$] pour voir si cela évite le chargement de toute la feuille.

    Sinon précisez nous le context technique ( asp.net, winform ... ) dans lequel vous effectuer cette requête.

    Cordialement

    lundi 19 décembre 2011 16:16
    Modérateur
  • le code suivant illustre que votre syntaxe limite bien l'exploration comme le reader. Par contre même punition qu'avec la syntaxe Excel... toute la feuille est chargée :(

            public void Can_Limit_Row_To_One_In_Reader() {
                 XlsxSrc xs = new XlsxSrc(@"c:\temp\UtXlsxSrc.xlsx", false);
                 // ===== nombre total de lignes
                 XlsxDataReader xsr = xs.ExecuteReaderFromQuery("select * from [Feuil1$]");
                 Int32 i = 0;
                 while (xsr.Read()) {
                     i++;
                 }
                 xsr.Close();
                 Assert.AreEqual(2, i);
                 // ===== 1 ligne via top
                 xsr = xs.ExecuteReaderFromQuery("select top 1 * from [Feuil1$]");
                 i = 0;
                 while (xsr.Read()) {
                     i++;
                 }
                 xsr.Close();
                 Assert.AreEqual(1, i);
                 // ===== 1 ligne via la syntaxe Excel
                 xsr = xs.ExecuteReaderFromQuery("select * from [Feuil1$1:1]");
                 i = 0;
                 while (xsr.Read()) {
                     i++;
                 }
                 xsr.Close();
                 xs.Close();
                 Assert.AreEqual(1, i);
             }
    



    thierry
    lundi 19 décembre 2011 17:05
  • le contexte technique... un programme .Net 4 en ligne de commande, studio 2010 sp1, fournisseur ole : Microsoft.ACE.OLEDB.12.0
    thierry
    lundi 19 décembre 2011 17:08
  • Dans ce cas si votre fichier excel est récent (2007 et + ) vous pourriez envisager d'utiliser l'API Open Xml au lieu du driver OleDb. Avec cet API, il est possible de lire le fichier soit en parsant tout le document (DOM) ou élément par élément (SAX).

    Dans votre cas l'approche SAX éviterait de charger tout le document : vous trouverez un exemple des 2 approches ici :

    How to: Parse and Read a Large Spreadsheet Document

    Cordialement

     

    lundi 19 décembre 2011 17:24
    Modérateur
  • Bonjour,

    Début de la mise en oeuvre de la suggestion : http://excelbysax.codeplex.com/

    A priori cela en restera là, sauf évolution du besoin.

    encore merci.


    thierry
    lundi 16 janvier 2012 13:44