2009-07-16 9 views
12

Sto tentando di aggiungere proprietà personalizzate a una cartella di lavoro che ho creato a livello di programmazione. Ho un metodo per ottenere e impostare le proprietà, ma il problema è che la cartella di lavoro restituisce null per la proprietà CustomDocumentProperties. Non riesco a capire come inizializzare questa proprietà in modo che possa aggiungere e recuperare proprietà dalla cartella di lavoro. Microsoft.Office.Core.DocumentProperties è un'interfaccia, così non posso andare a fare la seguenteAccesso alle proprietà del documento personalizzato di Excel a livello di programmazione

if(workbook.CustomDocumentProperties == null) 
    workbook.CustomDocumentProperties = new DocumentProperties; 

Ecco il codice che ho per ottenere e impostare le proprietà:

 private object GetDocumentProperty(string propertyName, MsoDocProperties type) 
    { 
     object returnVal = null; 

     Microsoft.Office.Core.DocumentProperties properties; 
     properties = (Microsoft.Office.Core.DocumentProperties)workBk.CustomDocumentProperties; 

     foreach (Microsoft.Office.Core.DocumentProperty property in properties) 
     { 
      if (property.Name == propertyName && property.Type == type) 
      { 
       returnVal = property.Value; 
      } 
      DisposeComObject(property); 
     } 

     DisposeComObject(properties); 

     return returnVal; 
    } 

    protected void SetDocumentProperty(string propertyName, string propertyValue) 
    { 
     DocumentProperties properties; 
     properties = workBk.CustomDocumentProperties as DocumentProperties; 

     bool propertyExists = false; 
     foreach (DocumentProperty prop in properties) 
     { 
      if (prop.Name == propertyName) 
      { 
       prop.Value = propertyValue; 
       propertyExists = true; 
      } 
      DisposeComObject(prop); 

      if(propertyExists) break; 
     } 

     if (!propertyExists) 
     { 
      properties.Add(propertyName, false, MsoDocProperties.msoPropertyTypeString, propertyValue, Type.Missing); 
     } 

     DisposeComObject(propertyExists); 

    } 

La linea proprietà = workBk.CustomDocumentProperties come DocumentProperties; imposta sempre le proprietà su null.

Questo sta usando Microsoft.Office.Core v12.0.0.0 e Microsoft.Office.Interop.Excell v12.0.0.0 (Office 2007)

risposta

10

ho guardato il mio codice e può vedere che l'accesso io le proprietà usando l'associazione tardiva. Non riesco a ricordare perché, ma inserirò del codice nel caso in cui sia d'aiuto.

object properties = workBk.GetType().InvokeMember("CustomDocumentProperties", BindingFlags.Default | BindingFlags.GetProperty, null, workBk, null); 

object property = properties.GetType().InvokeMember("Item", BindingFlags.Default | BindingFlags.GetProperty, null, properties, new object[] { propertyIndex }); 

object propertyValue = property.GetType().InvokeMember("Value", BindingFlags.Default | BindingFlags.GetProperty, null, propertyWrapper.Object, null); 

EDIT: ah, ora ricordo why. :-)

EDIT 2: risposta Jimbojones' - per usare la parola chiave dinamica - è una soluzione migliore (se il valore di facilità d'uso sopra il sovraccarico delle prestazioni di utilizzare dynamic).

+0

Esattamente il link che ho trovato, e ho postato il mio codice mentre si stavano scrivendo questo. +1 e accettato per te :-) –

+0

Aggiornamento per il collegamento su "perché": https://support.microsoft.com/en-us/kb/303296 –

7

Ho trovato la soluzione here.

Ecco il codice che ho finito con:

public void SetDocumentProperty(string propertyName, string propertyValue) 
    { 
     object oDocCustomProps = workBk.CustomDocumentProperties; 
     Type typeDocCustomProps = oDocCustomProps.GetType(); 

     object[] oArgs = {propertyName,false, 
       MsoDocProperties.msoPropertyTypeString, 
       propertyValue}; 

     typeDocCustomProps.InvokeMember("Add", BindingFlags.Default | 
            BindingFlags.InvokeMethod, null, 
            oDocCustomProps, oArgs); 

    } 

    private object GetDocumentProperty(string propertyName, MsoDocProperties type) 
    { 
     object returnVal = null; 

     object oDocCustomProps = workBk.CustomDocumentProperties; 
     Type typeDocCustomProps = oDocCustomProps.GetType(); 


     object returned = typeDocCustomProps.InvokeMember("Item", 
            BindingFlags.Default | 
            BindingFlags.GetProperty, null, 
            oDocCustomProps, new object[] { propertyName }); 

     Type typeDocAuthorProp = returned.GetType(); 
     returnVal = typeDocAuthorProp.InvokeMember("Value", 
            BindingFlags.Default | 
            BindingFlags.GetProperty, 
            null, returned, 
            new object[] { }).ToString(); 

     return returnVal; 
    } 

Alcuni gestione delle eccezioni è necessario a portata di mano se la proprietà doesnt esiste quando recuperate

3

risposta tarda a questa domanda, ma ho ideato un semplice metodo per aggiungere DocumentProperties personalizzate che potrebbero essere utili a qualcuno in futuro.

Il mio problema era che chiamare il metodo Add() con il tipo di sistema fornito da System.String.GetType() ha attivato un COMException: tipo mancata corrispondenza. Riferendosi al collegamento nelle risposte precedenti è chiaro che questo metodo si aspetta un tipo specifico carica, in modo che il codice che ha finito per lavorare per me è stato:

var custProps = (Office.DocumentProperties)this.CustomDocumentProperties; 
custProps.Add("AProperty", false, MsoDocProperties.msoPropertyTypeString, "AStringProperty"); 

Perché è un Ufficio CustomDocumentProperty aggiungerà la proprietà personalizzata senza difficoltà , ma se è necessario verificare l'esistenza o convalidare il valore quando la proprietà CustomDocument potrebbe non esistere, sarà necessario rilevare System.ArgumentException.

EDIT

Come sottolineato nel commento di Oliver Bock, questo è un Office 2007 e fino unica soluzione, per quanto ne so.

+1

Trovo (con Excel 2000) che non riesco a trasmettere workbook.CustomDocumentProperties a Office.DocumentProperties. Il codice delle riflessioni in altre risposte funziona comunque. –

+0

Ah, sì - Avrei dovuto notare (e lo ho fatto ora) che credo che questa sia una funzionalità di Office 2007 e solo su (anche se potrebbe funzionare nel 2003 - non ho più accesso a questo per testare). A mia difesa, è quello che stava usando il poster originale. – cori

12

Se si utilizza .NET 4.0, è possibile utilizzare la parola chiave dynamic per la fine del legame

Document doc = GetActiveDocument(); 
if (doc != null) 
{ 
    dynamic properties = doc.CustomDocumentProperties; 
    foreach (dynamic p in properties) 
    { 
     Console.WriteLine(p.Name + " " + p.Value); 
    } 
} 
Problemi correlati