2012-05-18 16 views
9

Ho riscontrato un problema nel recuperare i nomi dei fogli di lavoro da un foglio di calcolo Excel utilizzando OLEDB. Il problema è che quando utilizzo GetOleDbSchemaTable, il DataTable risultante ha più che solo i nomi effettivi del foglio di lavoro; ha righe extra per "Tabelle" che posso solo assumere sono usate internamente da Excel.Come ottenere l'elenco di SOLO i nomi dei fogli di lavoro Excel in Excel utilizzando OLEDB; filtrare i fogli di lavoro non mostrati nei metadati

Così, ad esempio, se ho un foglio di lavoro chiamato myWorksheet, il codice seguente potrebbe finire con un elenco che contiene myWorksheet $, myWorksheet $ PrintTable e myWorksheet $ _. Solo il primo record myWorksheet $ è per il foglio di lavoro effettivo. Gli altri sono solo spazzatura che non ho bisogno. Quando li guardi nei metadati, appaiono come normali tabelle, anche con il tipo di TABLE.

Per ora ho semplicemente filtrato manualmente qualsiasi cosa con "$ _" o "$ Print" nel nome, ma chissà quale altra funzione di Excel potrebbe rendere questi record extra in un formato diverso.

Qualcuno conosce il modo migliore per ottenere SOLO i nomi effettivi del foglio di lavoro e non queste tabelle interne che non sono fogli di lavoro? C'è qualcosa nei metadati che li differenziasse?

private ArrayList getXlsWorksheetNames(OleDb.OleDbConnection conn) 
    { 
     ArrayList wsList = new ArrayList(); 
     DataTable schemaTable; 

     try 
     { 
      conn.Open(); 
      schemaTable = conn.GetOleDbSchemaTable(OleDb.OleDbSchemaGuid.Tables, null); 

      foreach (DataRow row in schemaTable.Rows) 
      { 
       //form.appendToResultsTxt("Adding worksheet to list: " + Environment.NewLine + 
       // "Name = " + row.Field<string>("TABLE_NAME") + "," + Environment.NewLine + 
       // "Type = " + row.Field<string>("TABLE_TYPE") + "," + Environment.NewLine + Environment.NewLine); 
       wsList.Add(row.Field<string>("TABLE_NAME")); 
      } 
      conn.Close(); 
     } 
     catch (Exception ex) 
     { 
      if (this.mode == Cps2TxtUtilModes.GUI_MODE) 
      { 
       this.form.appendToResultsTxt(ex.ToString()); 
      } 
      throw; 
     } 

     return wsList; 
    } 

Ho letto attraverso l'articolo a questo link, ma non sembrano essere facendo nulla di diverso di me, e non vedo alcun filtraggio di tabelle non del foglio di lavoro in più, in modo Microsoft doesn sembra che abbia fornito la risposta giusta

http://support.microsoft.com/kb/318452

E ho anche guardato intorno un sacco di StackOverflow, come al filo dal link sottostante che era disponibile, ma non risolve questo problema.

Using Excel OleDb to get sheet names IN SHEET ORDER

Prima che qualcuno chiede, mi piacerebbe anche dire che in realtà non hanno il controllo su quali caratteristiche vengono utilizzati nel foglio di calcolo, quindi non posso solo dire loro "Non girare sul filtro "o" Non utilizzare le tabelle di stampa ".

Tutte le idee sono molto apprezzate. Grazie!

+1

Basta filtrare tutto ciò che non è con "$". L'ho usato per un po 'e non è mai mancato, anche quando ci sono tabelle pivot, elenchi filtrati, ecc. –

+0

Grazie; Lo farò. Come ho detto nel mio commento qui sotto, non è ideale perché si basa su un dettaglio di implementazione, ma se è quello che devo fare, allora così sia. – Jim

+0

La mia risposta alla domanda che hai collegato in sopra mostra come puoi farlo usando DAO, ma se non vuoi usare COM allora quella non è un'opzione. Tuttavia, l'addendum alla risposta di Esen mostra un altro modo rinominando il file .xlsx in .zip, aprendo il contenuto del file zip e leggendo uno dei file xml in esso contenuti per i nomi dei fogli. Non ho testato per vedere se i fogli nascosti appaiono lì e funzionerà solo su file 2007 (.xlsx), ma potrebbe valere la pena di sparare. –

risposta

2

Per esperienza, sembra che siano tutti quelli il cui nome finisce in un segno di dollaro. Mi sono imbattuto in scenari di clienti in cui sembravano apparire fogli di lavoro extra che non erano presenti nei dati - che in seguito si rivelarono essere fogli di lavoro nascosti in Excel!

+0

Sì, queste tabelle "nascoste" sono le cose che causano il problema. Probabilmente hai ragione che potrei cercare '$' come ultimo carattere nel nome. Tuttavia, alcune di queste tabelle "nascoste" hanno $ nei nomi, e io stavo cercando un modo definitivo per dire da qualche proprietà di metadati se una "Tabella" è un foglio di lavoro, o se è un altro tipo di Excel usato internamente tavolo. Grazie comunque per la risposta comunque. Qualcun altro sa qualcosa di metadati di Excel da differenziare? – Jim

+0

Non ho trovato un modo per vedere solo quali tabelle sono ancora visibili, suppongo che avremmo bisogno di usare Interop per qualcosa del genere. Non c'è nulla nella tabella GetOleDbSchemaTable per differenziarli. Se trovi qualcosa, per favore condividi e aggiornerò anche il mio programma! – Bridge

+0

Sicuramente non voglio usare interop! Grazie comunque per le informazioni.Ho appena diffidato del fatto che forse ci sono alcune funzionalità che non conosco che risulteranno in un "tavolo" non di lavoro che ha un $ alla fine del nome, ma suppongo che sia abbastanza buono per ora solo per supponiamo che non sia il caso. Basandosi su dettagli di implementazione fa schifo però. – Jim

0

Il primo modo che mi viene in mente è lo stesso modo in cui akash88 è elencato nel collegamento al collegamento Using Excel OleDb to get sheet names IN SHEET ORDER.

Puoi prendere l'approccio di akash88 e ripulirlo un po 'in modo che il codice sia più leggibile.

 var wsList = from s in schemaTable 
        where s.Field<string>("TABLE_NAME").Contains("$") 
        select s.Field<string>("TABLE_NAME"); 
+2

Leggi l'intero post e i commenti e vedrai che la tua risposta non è adeguata; restituirà record extra per le tabelle interne di Excel come le Tabelle dei filtri. Il post originale menzionava specificamente questo aspetto e chiedeva specificamente un modo per ottenere solo fogli di lavoro degli utenti effettivi dai metadati. Ho trovato da quando ho postato questo che non esiste un modo standard per distinguere i metadati se non basandosi sui dettagli di implementazione che tutti i fogli di lavoro degli utenti hanno un $ come ultimo carattere, o secondo all'ultimo carattere se il nome ha uno spazio e quindi è circondato da virgolette. – Jim

0

È possibile verificare EndsWith("$") invece di Contains("$") come di seguito:

List<String> lstsheetNames = new List<String>(); 
String sheetName; 
foreach (DataRow row in schemaTable.Rows) 
{ 
    sheetName = row.Field<string>("TABLE_NAME"); 
    String strTemp = sheetName.Split(' '); 

    if(strTemp.Length == 1 && sheetName.EndsWith("$")) 
     lstsheetNames.Add(sheetName.Substring(0, sheetName.Length - 1)); 

    else if(strTemp.Length > 1 && strTemp.GetValue(strTemp.Length - 1).ToString().EndsWith("$'")) 
     lstsheetNames.Add(sheetName.Substring(1, sheetName.Length - 3)); 
} 

Ho usato questo codice in un medesimo problema e funziona benissimo.

Modifica: Mi dispiace, non ho prestato attenzione a questo.Io ho cambiato il codice ora.Potrebbe non il modo migliore o più breve, ma funziona.

+2

Nessuno legge il vero post? Ho menzionato più volte che questo non funziona se il nome della tabella ha uno spazio, perché terminerà con una citazione invece di una $, e ho anche chiesto specificamente una soluzione reale in cui i metadati indicano una tabella utente e non una tabella interna, invece di fare affidamento solo su un dettaglio di implementazione che io chiaramente conosco già perché esiste nel mio OP. – Jim

4

La domanda è vecchia, ma per coloro che hanno trovato ora, il salto può essere fatto come si trova Jim ...

 // skip those that do not end correctly 
     foreach (DataRow row in schemTable.Rows) 
     { 
      string sheetName = row["TABLE_NAME"].ToString(); 
      if (!sheetName.EndsWith("$") && !sheetName.EndsWith("$'")) 
       continue; 
      Console.WriteLine(sheetName); 
     } 

Questo è il voluto sono o quelli che terminano con $ o quelli che terminano con $'.

Problemi correlati