Spørsmål? Ring tlf 94 30 21 81
Denne artikkelen vil vise hvordan en kan unngå problemer med ulike Office-/COM-versjoner ved å bruke late binding og reflection heller enn å importere Interop-biblioteker.
Early binding i sammenheng med office-automering innebærer at du legger inn en referanse til det aktuelle Office-biblioteket, og arbeider med objektene direkte. Fordelen her er at du får tilgang til Intellisense i Visual Studio, slik at programmeringen går lekende lett.
Microsoft har imidlertid gjort Office-automering til en liten hodepine for utviklere ved å stadig produsere nye versjoner av Office-bibliotekene, slik at early binding ikke blir et alternativ når en applikasjon skal distribueres til brukere som har ulike eller ukjente versjoner av disse bibliotekene.
Når du benytter et COM-bibliotek fra .NET, lages det en .NET-wrapper via Interop.
I Solution Explorer:
References -> Add reference -> COM -> Microsoft Word 10.0 Object Library
...
using Word;
...
ApplicationClass oWord = new ApplicationClass();
Documents oDocs = oWord.Documents;
Koden over funker gjerne helt greit, helt til du kommer til metoder med forskjellige parametre. I èn versjon av biblioteket tar Documents.Add-metoden 2 parametre, mens i en annen tar metoden 4 parametre. I en tredje tar den kanskje fem. Et cetera:
Versjon X: oDoc = oDocs.Add(ref oFile, ref oMissing);
Versjon Y: oDoc = oDocs.Add(ref oFile, ref oMissing, ref oMissing, ref oMissing);
Resultatet er at programmet vil krasje dersom ikke den installerte versjonen finnes på den aktuelle maskinen der applikasjonen kjører. Det finnes muligens en viss form for tilbake-kompatibilitet, men med gal versjon vil du også få problemer med å kompilere programmet ditt. Generelt dukker det stadig opp problemer når en bruker early binding.
Late binding i denne sammenhengen betyr at du bruker reflection til å koble opp mot COM. For å bruke denne teknikken må du kjenne til objekter, metoder og egenskaper i et aktuelt Office-bibliotek.
Type wordType = Type.GetTypeFromProgID( "Word.Application" );
// Word application-objektet:
object wordApplication = Activator.CreateInstance( wordType );
wordType.InvokeMember(
"Visible",
BindingFlags.SetProperty,
null,
wordApplication,
new object[] {
true
} );
// Hent Documents collection:
object wordDocuments = wordType.InvokeMember(
"Documents",
BindingFlags.GetProperty,
null,
wordApplication,
new object[] {
} );
// Åpne et gitt Word-dokument:
object wordDocument = wordType.InvokeMember(
"Open",
BindingFlags.InvokeMethod,
null,
wordDocuments,
new object[] {
System.IO.Path.Combine(
Environment.CurrentDirectory,
"MyWordDocument.doc" )
} );
// Referanse til bokmerker:
object bookmarks = wordType.InvokeMember(
"Bookmarks",
BindingFlags.GetProperty,
null,
wordDocument,
new object[] {
} );
// Referanse til et gitt bokmerke:
object bookmark = wordType.InvokeMember(
"Item",
BindingFlags.InvokeMethod,
null,
bookmarks,
new object[] {"asdf"
} );
// Referanse til bokmerkets range:
object range = wordType.InvokeMember(
"Range",
BindingFlags.GetProperty,
null,
bookmark,
new object[] {
} );
// Definèr hva som skal stå i bokmerket:
object text = wordType.InvokeMember(
"Text",
BindingFlags.SetProperty,
null,
range,
new object[] {"WOOOOOOOOOOOOOOORLD"
} );
Problemet med late binding er at det går mye tregere. Late binding skjer run time - dette betyr at .Net-rammeverket må lete opp et objekt, dets metoder og properties for hver linje som kjøres. Dette tar tid.
try{
//Early binding (dvs bruk det importerte biblioteket)
ApplicationClass oWord = new ApplicationClass();
....
}
catch{//nada}
//Hvis early binding-objektet er null, gå for late
if(oWord == null){
//Late binding
}
Dersom du følger denne oppskriften vil Word-/Excel-dokumentet åpnes raskt dersom rett Office-COM-versjon er installert (early binding), og saktere (late binding) dersom versjonen ikke er tilgjengelig. Og mens brukeren venter kan du kanskje gi en melding om at han kan be administrator om å installere versjon x.x.x av Word på maskinen, eller noe sånt.