Krok po kroku jak napisać prosty dodatek do MS Word 2010

O_o

Słowo wstępu:

Poniższy tekst opisuje sposób tworzenia dodatku do programu Word z pakietu Microsoft Office w wersji 2010, dla wersji 2007 wymagane mogą być niewielkie zmiany.
Poziom artykułu będzie daleki od profesjonalnego gdyż dopiero co napisałem mój pierwszy dodatek do Worda.
Poniższy dodatek będzie wyświetlał ilość znaków od wybranego miejsca w dokumencie do jego końca w małym okienku. Takie były wymagania klienta ( siostra ) więc taki będzie ten przykład ;)

  1. Szybki początek.

Teorii tu nie będzie, wszystko jest na MSDN.

-Stworzenie projektu: W kategorii C# ( lub dla masochistów Visual Basic ) w grupie Office\2010 należy wybrać "Word 2010 Add-in"
-Wersja framework'u: Według MSDN zalecany jest 4.0 lecz można wybrać w dół do 2.0, zalecam 3.5 - bo nie wszyscy mają 4.0 jeszcze ( siostra nie miała ;p ) Wybór wersji nie wpływa na konstrukcję dodatku więc można przebierać dowoli.
-Nazwa projektu - nazwa jest ważna, Office niezbyt pozwala na dwa dodatki o takiej samej nazwie. Dla tego przykładu weźmy nazwę "CharCounter35"

  1. Konstrukcja dodatku.

Interakcja z Word'em jest możliwa drogą pasywną ( zdarzenia ) oraz aktywną ( odwołania przez dostępne obiekty ).
Należy pamiętać że instancja dodatku jest współdzielona przez wszystkei aktywne dokumenty - więc należało by dodać obsługę wielu dokumentów, lecz w tym artyklue pominę ten "banalny" krok.

Główny kod dodatku zawiera się w klasie:

public partial class ThisAddIn

Nie polecam wprowadzać zmian w tej deklaracji.

Na początku mamy dostępne trzy metody:

 private void ThisAddIn_Startup(object sender, System.EventArgs e)
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
private void InternalStartup() // ukryta w #region VSTO generated code

Te metody to dwa główne zdarzenia wywoływane kolejno gdy dodatek jest załadowany ( następuje to gdy dokument staje się dostępny do edycji ) oraz gdy dodatek jest zwolniony ( zamknięty ostatni dokument Word'a ).
Trzecia metoda jest kluczowa do obsługi zdarzeń. W niej przypisuje się metody obsugi zdarzeń do odpowiednich delegatów. Zdarzeń jest ogrom, wszystkie opisane na MSDN'ie.
W ciele metody znajduje się wygenerowane przypisanie metod obsługi zdarzeń startup i Shutdown.

this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);

W analogiczny sposób dodajemy obsługę kolejnych zdarzeń. W tym przykładzie nie będą użyte żadne zdarzenia prócz tych dwóch.
Jest teoretycznie możliwe by dodać obsługę zdarzeń w innym miejscu w kodzie lecz jest to niezalecane gdyż może doprowadzić do dziwnych zjawisk.

  1. Zliczanie ilośći znaków.

Jako człowiek leniwy zalecam wykonanie tego przy użyciu klasy BackgrounWorker, nie będę się rozpisywać nad jej działaniem gdyż jest to nieistotne w tym artykule.
W tym momencie wystarczy wiedzieć że BackgroundWorker jest wygodną alternatywą wątków z klasy Thread.

a) BackgroundWorker ( kod piękny nie jest gdyż powstał metodą Copy&Paste we współpracy z MSDN )

        int start = 0;
        private void _DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            while(true) // nieskończona pęla
            {
                // obsługa wyłączenia BackgroundWorker'a
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else // akcja!
                {  
                    int n = 0;
                    try // blok try jest konieczny przy odwołaniu do dokumentu z poza zdarzeń
                    {
                        // zliczenie znaków pomięzy wybraną pozycją ( start ) a końcem dokumentu;
                        n = this.Application.ActiveDocument.Content.Text.Length-start-1;
                    }
                    catch (Exception) { continue; } // pominięcie zwrócenia wyników gdy wystąpił jakiś błąd.
                    // zwrócenie wartości.
                    worker.ReportProgress(0, n);
                }
            }
        }
        // zwrócenie wartości z BackgroundWorker'a
        private void _ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // odczytanie przekazanej wartości.
            int dat = (int)e.UserState;
            // wynik jest wyświetlany w kontrolce WinForms więc dostęp musi być thread safe.
            SetText(dat.ToString());
        }

b) Wypis danych:

        TextBox t = new TextBox();
        private void SetText(string text)
        {
            if (this.t.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                f.Invoke(d, new object[] { text });
            }
            else
            {
                this.t.Text = text;
            }
        }

c) Forma z danymi.

Możliwe jest dodanie własnej grupy na wstążce Office'a lecz nie pasowało to do tego projektu stąd dane wyświetlane są na skromenj foremce.
Sposób ten jest NIEzalecany, jest zły, prymitywny, sprawia problemy.

Artykuł ten nie jest o tworzeniu formy więc podam tylko kod.
Dobrym miejscem na tworzenie formy jest zdarzenie Startup:

        Button b = new Button();
        TextBox t = new TextBox();
        private Form f = new Form();
        private BackgroundWorker keycounter = new BackgroundWorker();
        string Text = "";
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            
            keycounter.WorkerSupportsCancellation = true;
            keycounter.WorkerReportsProgress = true;
            keycounter.DoWork += new DoWorkEventHandler(_DoWork);
            keycounter.ProgressChanged += new ProgressChangedEventHandler(_ProgressChanged);
            keycounter.RunWorkerAsync();

            f.Text = ":)";
            f.Height = 100; f.Width = 100;
            f.FormBorderStyle = FormBorderStyle.SizableToolWindow;
            f.TopMost = true;
            f.Left = 0;
            f.Top = 0;
            f.Show();
            b.Text = "ustaw";
            b.AutoSize = true;
            b.Click+=new EventHandler(b_Click);
            t.Top = b.Bottom;
            t.Height = 80;
            t.Text = "";
            t.Multiline = true;
            t.ReadOnly = true;
            f.Controls.Add(b);
            f.Controls.Add(t);
            
        }

A zwalnianie formy winno byc w zdarzeniu Shutdown

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
            keycounter.CancelAsync();
            f.Close();
        }
  1. Debugowanie.

Jedyne co trzeba posiadać to Visual Studio 2010 ( może i niższa wersja wystarczy ale po co użyać gdy jest nowsza ) i Office 2010.
Gdy te wymagania są spełnione wystarczy uruchomić projekt w trybie debugowania. Klawisz F5 lub ten zielony trójkącik.
Zostanie uruchomiony Office wraz z dodatkiem.

  1. Czyszczenie po sobie.

Debugowanie dodatku może zasyfić rejestr i ustawienia Office stąd zalecane jest wybranie z menu głównego opcji:
"Build\Clean Solution"

  1. Tworzenie instalki.

Wystarczy przełączyć tryb Debug na tryb Release i zbudować solucję. F6 albo "Build\Build Solution".
Pliki wymagane do isntalacji to ( gdy projekt nazywa się CharCounter35 ):
CharCounter35.dll
CharCounter35.dll.manifest
CharCounter35.vsto

Gdy projekt jest budowany na .NET 4.0 pojawiają się też pliki:
Microsoft.Office.Tools.Common.v4.0.Utilities.dll
Microsoft.Office.Tools.Common.v4.0.Utilities.xml
Microsoft.Office.Tools.Word.v4.0.Utilities.dll
Microsoft.Office.Tools.Word.v4.0.Utilities.xml

Plik VSTO jest plikiem uruchamialnym ( gdy jest zaisntalowany Office ). Instalacja jest tak prosta że każdy szary użytkownik da radę ją przeprowadzić.

I tak powstał Twój pierwszy dodatek do MS Office.

0 komentarzy