Vsto excel c примеры

Table of Contents

  • Introduction
  • Building the Sample

You can download the source code from this link Source
Code Link

Introduction

The main purpose of this article is to explain how to create simple Excel and Microsoft Word Add-Ins using Visual
Studio Tools for Office
 (VSTO).
VSTO is available as an add-in tool with Microsoft Visual Studio. Using Visual Studio we can develop our own custom controls for Office tools like Excel, Word and and so on.
In
our demo program We have used Visual Studio 2010 and Office 2007.

Building the Sample

This article explains a few basic things to create our own Custom Add-Ins for Excel and Word as follows.

1. Excel Add-Ins

  • Add text to any Excel selected active Excel cell.
  • Add an image to Excel from our Custom Control.
  • Load data from a database and display the search result data in Excel.

2. Word Add-Ins

  • Export Word to PDF.
  • Add Image to Word Document.
  • Add Table to Word document.

Description

Creating Excel Add-Ins

To create our own Custom Control Add-Ins for Excel.

Step 1

Create a new project and select Office 2007 Excel Add-In as in the following Image. Select your Project Folder and enter your Project Name.

Step 2

Now we can see that the Excel ThisAddIn.Cs file has been created in our project folder and we can find two default methods in this class as in the following image. “ThisAddIn_Startup
In this event we can display our own custom Control Add-Ins to Excel. We can see the details in the code part.

Step 3

Add a new UserControl to your project to create your own Custom Excel Control Add-In.

Right-click your project->Click Add New Item->Add User Control and Name the control as you wish. Add all your Controls and design your user control depending on your requirement.

In our example,We are performing 3 types of actions in User Controls.

  1. Add Text: In this button click event I will insert the text from the Text box to the Active Selected Excel Cell. Using “Globals.ThisAddIn.Application.ActiveCell
    we can get the current active Excel cell. We store the result in an Excel range and now using the range, value and color we can set our own text and colors to the active Excel Cell.

private void btnAddText_Click(object sender, EventArgs e)  

{  

    Excel.Range objRange = Globals.ThisAddIn.Application.ActiveCell;  

    objRange.Interior.Color = Color.Pink; //Active Cell back Color  

    objRange.Borders.Color = Color.Red;// Active Cell border Color  

    objRange.Borders.LineStyle = Excel.XlLineStyle.xlContinuous;  

    objRange.Value = txtActiveCellText.Text; //Active Cell Text Add  

    objRange.Columns.AutoFit();   

}

2.  Add Image: using
the Open File Dialog we can select our own image that needs to be added to the Excel file. Using the Excel.Shape we can add our selected image to the Excel file.

private void btnAddImage_Click(object sender, EventArgs e)  

        {  

            OpenFileDialog dlg = new OpenFileDialog();  

            dlg.FileName = "*";  

            dlg.DefaultExt = "bmp";  

            dlg.ValidateNames = true;  

            dlg.Filter = "Bitmap Image (.bmp)|*.bmp|Gif Image (.gif)|*.gif|JPEG Image (.jpeg)|*.jpeg|Png Image (.png)|*.png";  

            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)  

            {  

                Bitmap dImg = new Bitmap(dlg.FileName);  

                  Excel.Shape IamgeAdd = Globals.ThisAddIn.Application.ActiveSheet.Shapes.AddPicture(dlg.FileName,  

      Microsoft.Office.Core.MsoTriState.msoFalse,            Microsoft.Office.Core.MsoTriState.msoCTrue,  

          20, 30, dImg.Width, dImg.Height);  

            }  

            System.Windows.Forms.Clipboard.Clear();  

        }

Search and bind Db Data to Excel: Now
we can create our own Custom Search control to be used in Excel to search our data from the database and bind the result to the Excel file.

Creating the table

-- Create Table ItemMaster in your SQL Server - This table will be used for search and bind result to excel.  

CREATE
TABLE
[dbo].[ItemMasters](  

[Item_Code] [varchar](20)
NOT NULL,  

[Item_Name] [varchar](100)
NOT NULL)  

-- insert sample data to Item Master table  

INSERT
INTO
[ItemMasters] ([Item_Code],[Item_Name])  

VALUES
('Item001','Coke')  

INSERT
INTO
[ItemMasters] ([Item_Code],[Item_Name])  

VALUES
('Item002','Coffee')  

INSERT
INTO
[ItemMasters] ([Item_Code],[Item_Name])  

VALUES
('Item003','Chiken Burger')  

INSERT
INTO
[ItemMasters] ([Item_Code],[Item_Name])  

VALUES
('Item004','Potato Fry')

In the button search click event we search for the data from the database and bind the result to an Excel cell using “Globals.ThisAddIn.Application.ActiveSheet.Cells”.
This will add the result to the active Excel sheet.

private
void
btnSearch_Click(
object
sender, EventArgs e)  

{  

    try  

    {  

        System.Data.DataTable dt =
new
System.Data.DataTable();  

        String ConnectionString =
"Data Source=YOURDATASOURCE;Initial Catalog=YOURDATABASENAME;User id = UID;password=password";  

        SqlConnection con =
new
SqlConnection(ConnectionString);  

        String Query =
" Select Item_Code,Item_Name FROM ItemMasters Where Item_Name LIKE '"
+ txtItemName.Text.Trim() + "%'";  

        SqlCommand cmd =
new
SqlCommand(Query, con);  

        cmd.CommandType = System.Data.CommandType.Text;  

        System.Data.SqlClient.SqlDataAdapter sda =
new
System.Data.SqlClient.SqlDataAdapter(cmd);  

        sda.Fill(dt);  

        if
(dt.Rows.Count <= 0)  

        {  

            return;  

        }  

        Globals.ThisAddIn.Application.ActiveSheet.Cells.ClearContents();    

        Globals.ThisAddIn.Application.ActiveSheet.Cells[1, 1].Value2 =
"Item Code";     

        Globals.ThisAddIn.Application.ActiveSheet.Cells[1, 2].Value2 =
"Item Name";     

        for
(int
i = 0; i <= dt.Rows.Count - 1; i++)  

        {     

            Globals.ThisAddIn.Application.ActiveSheet.Cells[i + 2, 1].Value2 = dt.Rows[i][0].ToString();        

            Globals.ThisAddIn.Application.ActiveSheet.Cells[i + 2, 2].Value2 = dt.Rows[i][1].ToString();  

        }  

    }  

    catch
(Exception ex)  

    {  

    }  

}

Step 4

Now we have created our own User Control to be added to our Excel Add-Ins. To add this user control to our Excel Add-In as we have already seen that the Excel Addin class “ThisAddIn.Cs” has start and stop events. Using
the Office “CustomTaskpane” we can add our user control to Excel as an Add-In as in the following.

private
Microsoft.Office.Tools.CustomTaskPane customPane;  

private
void
ThisAddIn_Startup(
object
sender, System.EventArgs e)  

{  

    ShowShanuControl();  

}  

public
void
ShowShanuControl()  

{  

    var txtObject =
new
ShanuExcelADDIn();  

    customPane =
this.CustomTaskPanes.Add(txtObject,
"Enter Text");  

    customPane.Width = txtObject.Width;  

    customPane.Visible =
true;  

}

Step 5

Run your program and now we can see our user control has been added in the Excel File as an Add-In.
Next we will see how to create Add-Ins for Word Documents using a Ribbon Control.

Creating Word Add-Ins: 
In my example I have used Visual Studio 2010 and Office 2007.
The following describes how to create our own Custom Control Add-Ins for Word.

Step 1

Create a new project and select Office 2007 Word AddIn as in the following Image. Select your Project Folder and enter your Project Name.

Step 2

Add a new Ribbon Control to your project to create your own Word Control Add-In.

Right-click your project then click Add New Item -> Add Ribbon Control and name the control as you wish. 

Add all your controls and design your user control depending on your requirements. By default in our Ribbon Control we can see a “RibbonGroup”. We can add all our controls to the Ribbon Group. Here
in my example I have changed the Group Label Text to “SHANU Add-In”. I have added three Ribbon Button Controls to the group. We can add an image to the Ribbon Button Controls and set the properties of the Button Control Size as “
RibbobControlSizeLarge”. 

Here I have added three Button Controls for export the Word as a PDF, add an image to Word and add a table to the Word file.

Step 3

Export to PDF File Button Click.

Using the “Globals.ThisAddIn.Application.ActiveDocument.ExportAsFixedFormat” we can save the Word document to the PDF file. I have used the Save file dialog to save the PDF file into our selected path.

private
void
btnPDF_Click(
object
sender, RibbonControlEventArgs e)  

{  

    SaveFileDialog dlg =
new
SaveFileDialog();  

    dlg.FileName =
"*";  

    dlg.DefaultExt =
"pdf";  

    dlg.ValidateNames =
true;  

    if
(dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)  

    {  

        Globals.ThisAddIn.Application.ActiveDocument.ExportAsFixedFormat(dlg.FileName, word.WdExportFormat.wdExportFormatPDF, OpenAfterExport:
true);  

    }              

}

Step 4

Here we will add an image to Word. Using the Open File Dialog we can select our own image to be added to the Word file. Using the “Globals.ThisAddIn.Application.ActiveDocument.Shapes.AddPicture” method we can add our
selected image to the Word file.

private
void
btnImage_Click(
object
sender, RibbonControlEventArgs e)  

{  

    OpenFileDialog dlg =
new
OpenFileDialog();  

    dlg.FileName =
"*";  

    dlg.DefaultExt =
"bmp";  

    dlg.ValidateNames =
true;  

    dlg.Filter =
"Bitmap Image (.bmp)|*.bmp|Gif Image (.gif)|*.gif|JPEG Image (.jpeg)|*.jpeg|Png Image (.png)|*.png";  

    if
(dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)  

    {  

        Globals.ThisAddIn.Application.ActiveDocument.Shapes.AddPicture(dlg.FileName);  

    }  

}

Step 5

Here we will add a table to Word. Using the “Globals.ThisAddIn.Application.ActiveDocument.Tables” method we can add a table to the Word file. In my example I have created a table with 4 columns and 3 rows.

private
void
button1_Click(
object
sender, RibbonControlEventArgs e)  

{  

    Globals.ThisAddIn.Application.ActiveDocument.Tables.Add(Globals.ThisAddIn.Application.ActiveDocument.Range(0, 0), 3, 4);  

.ThisAddIn.Application.ActiveDocument.Tables[1].Range.Shading.BackgroundPatternColor = Microsoft.Office.Interop.Word.WdColor.wdColorSeaGreen;  

    Globals.ThisAddIn.Application.ActiveDocument.Tables[1].Range.Font.Size = 12;  

    Globals.ThisAddIn.Application.ActiveDocument.Tables[1].Rows.Borders.Enable = 1;  

}

Step 6

Run your program and now you will see your own Ribbon Control has been added to the Word file as an Add-In.

  

You can download the source code from this link Source
Code Link

Edit: Great, I just noticed that I missed a big part of your question, getting updates and deletes back to the worksheet. I have absolutely no idea if that is possible but I think that makes my solution worthless. I’ll leave it here anyway, maybe it can help in any way.


Why do you need VSTO? As far as I know VSTO is used for Office Add-Ins. But since you want to show the data in a DataGridView I assume that you have a WinForms application that should just access a workbook. In this case you can simply open the workbook by using Office Interop. Just add a reference to Microsoft.Office.Interop.Excel to your project and add a using Microsoft.Office.Interop.Excel; statement.

MSDN reference documentation for Excel Interop can be found here: http://msdn.microsoft.com/en-us/library/ms262200%28v=office.14%29.aspx

I’ll give you the Excel part, maybe someone else can do the rest.

First, open Excel and the workbook:

Application app = new Application();
// Optional, but recommended if the user shouldn't see Excel.
app.Visible = false;
app.ScreenUpdating = false;
// AddToMru parameter is optional, but recommended in automation scenarios.
Workbook workbook = app.Workbooks.Open(filepath, AddToMru: false);

Then somehow get the correct worksheet. You have a few possiblities:

// Active sheet (should be the one which was active the last time the workbook was saved).
Worksheet sheet = workbook.ActiveSheet;
// First sheet (notice that the first is actually 1 and not 0).
Worksheet sheet = workbook.Worksheets[1];
// Specific sheet.
// Caution: Default sheet names differ for different localized versions of Excel.
Worksheet sheet = workbook.Worksheets["Sheet1"];

Then get the correct range. You didn’t specify how you know where the needed data is, so I’ll assume it is in fixed columns.

// If you also know the row count.
Range range = sheet.Range["A1", "D20"];
// If you want to get all rows until the last one that has some data.
Range lastUsedCell = sheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell);
string columnName = "D" + lastUsedCell.Row;
Range range = sheet.Range["A1", columnName];

Get the values:

// Possible types of the return value:
// If a single cell is in the range: Different types depending on the cell content
// (string, DateTime, double, ...)
// If multiple cells are in the range: Two dimensional array that exactly represents
// the range from Excel and also has different types in its elements depending on the
// value of the Excel cell (should always be that one in your case)
object[,] values = range.Value;

That two dimensional object array can then be used as a data source for your DataGridView. I haven’t used WinForms for years so I don’t know if you can bind it directly or first need to get the data into some specific format.

Finally close Excel again:

workbook.Close(SaveChanges: false);
workbook = null;
app.Quit();
app = null;
// Yes, we really want to call those two methods twice to make sure all
// COM objects AND all RCWs are collected.
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();

Correctly closing Excel after using Interop is a task itself because you have to make sure that all references to COM objects have been released. The easiest way I have found to do this is to do all the work except opening and closing Excel and the workbook (so my first and last code block) in a seperate method. This ensures that all COM objects used in that method are out of scope when Quit is called.

1. Вступление

Привет всем!

Ранее мной была написана статья о создании расширения для Microsoft Excel на C#, где я описывал, как с помощью библиотеки Excel-DNA можно создать надстройку, с добавлением пользовательского интерфейса на ленту, и дополнительные функции, для приложения Microsoft Excel. Библиотека Excel-DNA, надо сказать, очень неплохая библиотека, но она имеет как свои плюсы, так и очень существенные минусы.

К плюсам этой библиотеки можно отнести то, что она позволяет создавать расширения для Excel начиная с версии 2007 и выше. Так же плюсом является довольно простой интерфейс для создания дополнительных пользовательских функций, позволяя расширить и существенно улучшить встроенный набор функций Excel. Но, на этом, собственно, плюсы и заканчиваются.

А теперь минусы.

Создание визуального интерфейса надстройки на пользовательскую ленту уже не такое удобное и требует дополнительного стороннего приложения в виде какого-нибудь ribbon xml editor, если Вы, конечно, не желаете довольно досконально изучить все особенности xml-разметки ленты ribbon, чтобы создавать её самому, как говориться, ручками. Хотя, если Вы это действительно изучите, то Вам будет конечно же большой плюс.

Но, кроме не самого приятного способа создания пользовательского интерфейса, ещё и взаимодействие с ним не очень удобное. Дело в том, что прямой доступ к ленте ribbon, при использовании библиотеки Excel-DNA, крайне ограничен, и некоторые взаимодействия с элементами на этой ленте можно произвести только посредством хитрых конструкций, основанных на обработчиках событий, да и то надёжность этих конструкций вызывает вопросы.

Ну и ещё один довольно большой минус — это то, что эта библиотека позволяет создавать надстройки исключительно только для Excel, лишая всякой возможности создать надстройку, скажем, для Word. Кстати, именно это ограничение всё время и мотивировало меня найти какую-либо более универсальную технологию для создания надстроек. И такой технологией оказалось VSTO расширение для Microsoft Office.

2. VSTO расширения для Microsoft Office

Что же такое VSTO? VSTO это Visual Studio Tools for Office, то есть это набор инструментов визуальной среды разработки приложений Visual Studio для Office.

Вообще VSTO не является чем-то совсем уж новым, расширения VSTO можно было создавать еще для Office 2013. Но, что важно, не ниже. И это как раз то, что является его довольно большим минусом. Проблема заключается в том, что в организациях, которые когда-то закупили лицензионный Office 2007, он чаще всего так до сих пор и работает. А что, простой, надежный, без лишних прибамбасов, можно сказать на 100% покрывающий все потребности работы с документами, и закупка более новой версии в целом, вроде как и не имеет смысла, можно сказать пустая трата денег. Но вот расширения VSTO на них встанут едва ли, только если может быть с помощью каких-нибудь «костылей». Так что, если появилась потребность в создании собственных надстроек в приложениях Microsoft Office, то это можно считать существенным мотивом к обновлению ПО, если оно не соответствует требованиям.

Как можно понять из названия VSTO, для его создания в первую очередь конечно же нужен Visual Studio,

на данный момент актуальной версией которой является 2019, и его дополнительный инструмент «Разработка надстроек для Office и SharePoint«.

Добавляемые при этом в Visual studio дополнительные шаблоны и предоставляют наборы инструментов для создания надстроек к Word, Excel, PowerPoint и многих других приложений Microsoft.

Так же в дальнейшем наверняка понадобится инструмент для установки своих созданных надстроек на другие компьютеры, и для этого подойдет расширение «Microsoft Visual Studio Installer Projects«,

которое можно установить с помощью инструмента «управление расширениями«.

Надстройку для Office можно создавать как на уровне документа, то есть эта надстройка будет запущена только при открытии конкретного документа, в котором она была создана, так и на уровне приложения, когда надстройка будет запускаться вместе с приложением независимо от открываемого документа.

Принцип создания надстройки для всех приложений (Word, Excel, PowerPoint и т.д.) в общем-то одинаковый. Для начала создаётся некий интерфейс на пользовательскую ленту инструментов, а затем обрабатываются события, инициируемые элементами этого созданного интерфейса, например, нажатие кнопки. Фактически создание надстройки отличаются в основном только объектной моделью приложения, поэтому, прежде чем создавать надстройку, скажем для Word, вначале нужно изучить объектную модель Word, структуру его документа и API, предоставляющий набор методов для работы с ним. Разумеется, то же касается и остальных приложений пакета Microsoft Office.

Кстати у технологии VSTO я вижу еще один минус. Я пока что так и не нашел, как с помощью VSTO просто расширить набор функций Excel, как это возможно посредством библиотеки Excel-DNA, а ведь это весьма полезная функция.

3. Приступаем к разработке надстройки

А теперь пример создания очень простенькой надстройки для Word, которая все что и будет уметь делать, так это вставлять в документ в текущую позицию фразу «Привет Мир!», ну или за место слова «Мир» будет вставляться указанное имя. При этом можно будет оценить преимущества разработки расширений VSTO по отношению к библиотеке Excel-DNA, если Вы читали мою статью об этой библиотеке.

И так, после того как инструмент «Разработка надстроек для Office и SharePoint» будет добавлен в Visual Studio, в нём появятся множество дополнительных шаблонов. Среди этих шаблонов нас в данный момент интересует шаблон «Надстройка VSTO для Word«.

Кстати, как можно увидеть на изображении выше, рядом так же находятся шаблоны для создания Документа VSTO для Word, и Шаблона VSTO для Word, которые позволяют соответственно создать конкретный документ Word, расширенный дополнительным функционалом, или шаблон документа, который далее будет генерировать документы Word.

Создадим новый проект надстройки VSTO для Word и назовём его «HelloWoldAddIn», на что в ответ будет получен следующий автоматически сгенерированный код:

Код на C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Word = Microsoft.Office.Interop.Word;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Word;

namespace HelloWoldAddIn
{
    public partial class ThisAddIn
    {
        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region Код, автоматически созданный VSTO

        /// <summary>
        /// Требуемый метод для поддержки конструктора — не изменяйте 
        /// содержимое этого метода с помощью редактора кода.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
        
        #endregion
    }
}

Класс ThisAddIn, который был автоматически создан, является наследником класса Microsoft.Office.Tools.AddInBase, который, в свою очередь, предоставляет доступ к объектной модели текущего приложения посредством поля Application, возвращающего объект, представляющий экземпляр этого приложения.

Изначально в этом классе представлены всего лишь два обработчика событий — ThisAddIn_Startup, выполняющий код при загрузке надстройки и позволяющий произвести какую-либо инициализацию этой надстройки при запуске приложения. И ThisAddIn_Shutdown, который наоборот выполняет код перед закрытием приложения, и позволит сохранить настройки Вашей надстройки.

Но, с помощью только этих двух обработчиков многого не сделаешь, для работы нужна хотя бы одна какая-нибудь кнопка, которую можно было бы нажать в нужный момент работы с документом. И эту кнопку конечно же можно создать на ленте пользовательского интерфейса. Поэтому следующая задача — добавить в проект «Ленту«, и чтобы было удобнее её редактировать, стоит выбрать именно ленту в визуальном конструкторе,

после чего, собственно, и появится конструктор вкладки TabAddIns на ленте, пока еще пустой. Эту вкладку представляет класс Ribbon1, который является наследником класса Microsoft.Office.Tools.Ribbon.RibbonBase, который, в свою очередь, представляет базовый класс для настроек ленты Microsoft Office.

Далее, используя возможности визуального конструктора, панель элементов и поле свойства элементов, не составит никакого труда создать визуальный вид своей будущей надстройки.

И вот теперь в надстройке наконец-то появилась такая нужная нам кнопка, которую я назвал «Привет Мир!». Так же, для небольшой демонстрации некоторых возможностей, я сразу же добавил текстовое поле «Имя», из которого будет браться указанное имя для замены слова «Мир» во вставляемой этой надстройкой фразе.

При желании можно изменить имя группы вкладки, я свою группу назвал просто «Моя надстройка», а также можно переименовать саму вкладку, имя по умолчанию которой «TabAddIns». Если оставить имя как есть, то надстройка появиться в ленте на общей вкладке под названием «Надстройки», если же переименовать, то название вкладки, в которой появиться надстройка, соответственно измениться.

Далее эту ленту, а точнее вкладку на ленте, надо добавить к нашей надстройке и сделать это можно в переопределенном методе CreateRibbonExtensibilityObject.

protected override IRibbonExtensibility CreateRibbonExtensibilityObject() {
    Ribbon1 ribbon = new Ribbon1();
    return Globals.Factory.GetRibbonFactory().CreateRibbonManager(
        new Microsoft.Office.Tools.Ribbon.IRibbonExtension[] { ribbon });
}

И теперь, запустив приложение кнопкой Пуск,

откроется приложение Word, в котором уже можно найти созданную надстройку.

Правда толку от нее мало, кнопка пока что еще не работает. Поэтому, для того чтобы надстройка заработала, осталось на кнопку «Привет мир» добавить какой-нибудь программный код. Для этого находим эту кнопку в конструкторе, и, дважды на неё нажав мышкой, добавляем ей обработчик события, начальный код которого генерируется в классе ленты Ribbon1.

Но далее возникает одна проблемка. Сама лента Ribbon не имеет доступа к Application, и соответственно не может получить экземпляр текущего приложения для работы с ним и его документами. Так что писать код обработчика события нажатия кнопки прямо в классе Ribbon это плохая идея. Но это проблема решается довольно просто — нужно добавить новое событие, например, ButtonClicked, самому классу Ribbon, и при нажатии кнопки на ленте запустить обработчик этого нового события. А сам программный код этого обработчика определить в классе ThisAddIn, который уже вполне имеет доступ к Application. И кроме того, через этот обработчик, основанный на стандартном делегате Action, в класс ThisAddIn можно передать экземпляр текущего класса Ribbon, что позволит получить полноценный доступ к своей вкладке на ленте и всем её компонентам.

    public partial class Ribbon1 {
        public event System.Action<Ribbon1> ButtonClicked;
        private void Ribbon1_Load(object sender, RibbonUIEventArgs e) {
            
        }

        private void btnHelloWorld_Click(object sender, RibbonControlEventArgs e) {
            ButtonClicked?.Invoke(this);
        }
    }
    public partial class ThisAddIn
    {

        . . .

        protected override IRibbonExtensibility CreateRibbonExtensibilityObject() {
            Ribbon1 ribbon = new Ribbon1();
            ribbon.ButtonClicked += Ribbon_ButtonClicked;
            return Globals.Factory.GetRibbonFactory().CreateRibbonManager(
                new Microsoft.Office.Tools.Ribbon.IRibbonExtension[] { ribbon });
        }

        private void Ribbon_ButtonClicked(Ribbon1 ribbon) {
            // Если в текстовом поле на ленте указано имя, то возьмем его. Иначе имя будет Мир.
            string _name = ribbon.ebHelloWorld.Text == "" ? "Мир" : ribbon.ebHelloWorld.Text;
            // Вставим в текущую позицию текст "Привет" и определенное выше имя.
            Application.Selection.Text = $"Привет {_name}!";
        }
    }

Ну вот надстройка и готова, осталось её запустить, и проверить её работу.

Да, кстати, после того как Вы протестируете надстройку, она останется в приложении Word и после закрытия Visual Studio, что не совсем правильно, так как эта надстройка пока еще только тестовая. Поэтому перед тем как завершить работу в Visual Studio не забудьте очистить собранный проект.

4. Дополнительные возможности надстройки

Надстройки VSTO удобны тем, что они позволяют использовать практически любые библиотеки и возможности NET Framework, версию которой Вы выберите перед началом создания надстройки. А это значит, что при желании Вы можете в документ загрузить какую-нибудь информацию, например, из базы данных или прямо с интернета, можете отправить что-нибудь из документа по электронной почте или даже наоборот получить электронную почту сразу в свой документ.

И конечно же имея такие возможности, наверняка рано или поздно возникнет вопрос с хранением некоторых настроек. Ну, в случае VSTO на уровне документа настройки, наверное, можно было бы хранить прямо в самом документе. В Word это может быть некоторый скрытый текст, с именованной закладкой для быстрого доступа к настройкам. В Excel можно использовать какую-либо ячейку. Но вот в надстройках VSTO на уровне приложения конкретного документа нет. Поэтому в этом случае для хранения настроек подойдёт системный реестр или просто обычный текстовый документ, расположенный, например, в документах текущего пользователя. Вот, как-то так:

Код на C#

public partial class ThisAddIn
{
    const string FILE_NAME = "HelloWordAddIn.txt";
    string name = "";

    private void ThisAddIn_Startup(object sender, System.EventArgs e)
    {
        name = LoadName();
    }

    private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
    {
    }

    #region Код, автоматически созданный VSTO

    /// <summary>
    /// Требуемый метод для поддержки конструктора — не изменяйте 
    /// содержимое этого метода с помощью редактора кода.
    /// </summary>
    private void InternalStartup()
    {
        this.Startup += new System.EventHandler(ThisAddIn_Startup);
        this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
    }

    #endregion

    protected override IRibbonExtensibility CreateRibbonExtensibilityObject() {
        Ribbon1 ribbon = new Ribbon1();
        ribbon.ButtonClicked += Ribbon_ButtonClicked;
        return Globals.Factory.GetRibbonFactory().CreateRibbonManager(
            new Microsoft.Office.Tools.Ribbon.IRibbonExtension[] { ribbon });
    }

    private void Ribbon_ButtonClicked(Ribbon1 ribbon) {
        // Определим какое имя должно быть указно при нажатии кнопки.
        string _name = 
            ribbon.ebHelloWorld.Text == "" ? (string.IsNullOrEmpty(name) ? "Мир" : name) 
            : ribbon.ebHelloWorld.Text;
        // Вставим в текущую позицию текст "Привет" и определенное выше имя.
        Application.Selection.Text = $"Привет {_name}!";
    }

    /// <summary>
    /// Получает имя из файла в директории "Мои документы"
    /// </summary>
    /// <returns></returns>
    private string LoadName() {
        string _name = "";
        // Для начала надо узнать путь к директорию "Мои документы" 
        // текущего пользователя,
        string myDocuments = 
            Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        // и сформировать полный путь к текстовому файлу, 
        // в котором должно быть указано имя.
        string path = $@"{myDocuments}{FILE_NAME}";

        // Если этого файла нет,
        if (!File.Exists(path))
            // то надо его создать, и сразу закрыть.
            File.Create(path).Close();

        try {
            // Далее надо открыть текстовый файл,
            using (StreamReader sr = 
                new StreamReader($@"{myDocuments}{FILE_NAME}", Encoding.UTF8)) {
                // и считать из него указанное имя.
               _name = sr.ReadLine();
            }
        } catch (FileNotFoundException) {
            // Если во время открытия файла возникла ошибка, 
            // значит пусть имя останется пустым.
            _name = "";
        }
        return _name != null ? _name : "";
    }
}

В этом коде был добавлен метод LoadName, который находит в директории документов пользователя файл «HelloWordAddIn.txt» и считывает из него имя, которое нужно поприветствовать. Чтобы постоянно не обращаться к файлу, имя считывается один раз при запуске настройки из метода ThisAddIn_Startup, и запоминается в глобальной переменной name, к которой уже в любой момент могут обратиться все желающие.

Единственное что ещё хотелось бы сделать, так это инициализировать пользовательский интерфейс надстройки при запуске, то есть, если в файле настроек указано имя, то чтобы это имя сразу же отображалось в текстовом поле в надстройке на пользовательской ленте.

Сделать это можно в классе ленты Ribbon в методе Ribbon1_Load, который срабатывает при загрузке ленты в приложении Office. Но делать это прямо в классе ленты опять же будет не целесообразно, так как прямой связи с классом ThisAddIn он не имеет, а ведь именно в нём находятся данные для загрузки имени из файла. Зато есть смысл добавить классу Ribbon ещё одно событие RibbonLoad, обработчик которого будет запускаться при загрузке ленты.

И тогда класс Ribbon примет следующий вид:

    public partial class Ribbon1 {
        public event System.Action<Ribbon1> RibbonLoad;
        public event System.Action<Ribbon1> ButtonClicked;

        private void Ribbon1_Load(object sender, RibbonUIEventArgs e) {
            RibbonLoad?.Invoke(this);
        }

        private void btnHelloWorld_Click(object sender, RibbonControlEventArgs e) {
            ButtonClicked?.Invoke(this);
        }
    }

а в классе ThisAddIn тогда немного изменится метод CreateRibbonExtensibilityObject.

    protected override IRibbonExtensibility CreateRibbonExtensibilityObject() {
        Ribbon1 ribbon = new Ribbon1();
        ribbon.RibbonLoad += Ribbon_RibbonLoad;
        ribbon.ButtonClicked += Ribbon_ButtonClicked;
        return Globals.Factory.GetRibbonFactory().CreateRibbonManager(
            new Microsoft.Office.Tools.Ribbon.IRibbonExtension[] { ribbon });
    }

В нем добавляется обработчик на новое, только что созданное, событие. И, соответственно, добавиться метод Ribbon_RibbonLoad,

        /// <summary>
        /// Обработка события возникающего при загрузке надстройки на ленте Ribbon
        /// </summary>
        /// <param name="ribbon"></param>
        private void Ribbon_RibbonLoad(Ribbon1 ribbon) {
            ribbon.ebHelloWorld.Text = name;
        }

в котором и происходит инициализация пользовательского интерфейса ленты, а точнее, перед открытием приложения в текстовое поле заносится указанное в файле имя.

5. Ручная установка надстройки

Теперь, когда надстройка готова, её надо установить. Для того чтобы Microsoft Word увидел и подключил надстройку на другом компьютере, проект надстройки надо собрать уже не в режиме разработки (Debug), а в режиме развертывания (Release). В выходном каталоге, примерно где-то здесь: C:UsersUsersourcereposHelloWoldAddInHelloWoldAddInbinRelease, будут скомпилированы несколько файлов. Нас интересуют четыре из них:

  • HelloWoldAddIn.dll
  • HelloWoldAddIn.dll.manifest
  • HelloWoldAddIn.vsto
  • Microsoft.Office.Tools.Common.v4.0.Utilities.dll

Все эти четыре файла нужно скопировать куда-нибудь в одну папку. Но, для того чтобы Word увидел надстройку, нужна еще соответствующая запись в системном реестре. А точнее, в ветке реестра HKEY_CURRENT_USERSoftwareMicrosoftOfficeWordAddins (если приложение Excel, то и ветка соответствующая), нужно добавить раздел нашей надстройки, например, HelloWoldAddIn. В этом разделе нужно создать четыре параметра:

  • строковый параметр «Description»
  • строковый параметр «FriendlyName»
  • параметр DWORD (32 бита) «LoadBehavior»
  • строковый параметр «Manifest»

и заполнить их примерно как указано на изображении ниже.

Параметр «Description» — это понятно, описание надстройки.

Параметр «FriendlyName» — это то, как надстройка будет выглядеть в списке надстроек в приложении Microsoft.

Параметр «LoadBehavior» равный 3 означает, что надстройка включена.

Самый сложный получается параметр «Manifest«, тут указан путь к файлам надстройки. Но, надо обязательно учесть, что перед началом пути стоит префикс «file:///», да-да, именно с треся слешами, а в конце пути указан суффикс «|vstolocal» и именно с «пайпом» в начале суффикса. А сам путь должен указывать на конкретный файл с расширением «vsto».

Если Вы все правильно сделаете, то запустив приложение Word, после нескольких предупреждений о нарушении безопасности, на ленте интерфейса Вы увидите свою надстройку. А если зайти в параметры Word, то на вкладке «Надстройки» будет информация о добавленной надстройке.

Так же, если зайти в «Управление надстройками COM«, то в списке надстроек будет отображаться Ваша надстройка, которую при желании можно временно отключить, убрав галочку напротив неё.

Если параметры реестра прописаны в ветке «HKEY_CURRENT_USER«, то надстройка будет доступна только текущему пользователю Windows, а если те же параметры прописать в ветке «HKEY_LOCAL_MACHINE«, то надстройка станет доступна для всех пользователей системы.

6. Установка надстройки с помощью установщика Windows

Но конечно же устанавливать надстройку вручную очень неудобно, поэтому гораздо лучше создать установщик, который всё сделает сам. Поэтому, если Вы все ещё не установили себе расширение «Microsoft Visual Studio Installer Projects«, то самое время это сделать.

Далее надо добавить проект установщика (Setup Project) в решение,

после чего сразу откроется вкладка «File System«. Если же она не открылась, то открыть её можно самому, нажав правой кнопкой мыши на проекте установщика, и в появившемся меню из «View» выбрать пункт «Файловая система«.

Во вкладке файловой системы надо указать, какие файлы нужны для работы. Для этого надо вызвать меню правой кнопкой мыши на разделе «Application Folder«, и из пункта «Add» выбрать подпункт «Выходной элемент проекта…«.

Появится окно «Добавление выходной группы проекта«, в котором надо выбрать пункт «Основные выходные файлы» и нажать кнопку «ОК».

После этого в разделе «Application Folder» появится список файлов. Это и есть те файлы, которые далее будут скопированы в рабочий раздел надстройки, и которые должны отвечать за её работу.

Но этот список надо немного скорректировать, что-то надо в него добавить, а что-то из него удалить. А именно.

В этом списке в данный момент не хватает двух важных файлов манифеста надстройки Word:

  • HelloWoldAddIn.dll.manifest
  • HelloWoldAddIn.vsto

Чтобы их добавить нужно снова вызвать контекстное меню раздела «Application Folder» и из пункта меню «Add» выбрать теперь уже подпункт «Файл…«. Откроется окно выбора файлов, в котором надо найти эти файлы манифеста. Найти их можно, как я уже указывал ранее, в выходном каталоге проекта надстройки, примерно где-то здесь: C:UsersUsersourcereposHelloWoldAddInHelloWoldAddInbinRelease. Если этот каталог пустой, значит Вы просто забыли собрать проект надстройки в режиме развертывания (Release), сделайте это. А далее надо добавить эти два файла в список выходных файлов.

А теперь в списке ещё остались файлы, которые в рабочем каталоге надстройки совершенно не нужны, их надо исключить из списка выходных файлов. Это удобнее делать из окна «Обозревателя решений«. Чтобы исключить файл из списка надо выбрать его в обозревателе, после чего в окне свойств установить значение параметра «Exclude» в True. После этого этот файл в «Обозревателе решений» примет вид как исключённый, а из списка выходных файлов и вовсе исчезнет.

Исключить из списка нужно все файлы из-под раздела обнаруженных зависимостей («Detected Dependencies»), за исключением платформы «Microsoft .NET Framework» или любой сборки, завершающейся ** *.Utilities.dll**

Должно получиться примерно вот так:

Сразу же можно настроить путь к выходным файлам надстройки. Для этого надо выбрать раздел «Application Folder«, после чего в окне свойств в параметре «DefaultLocation» можно будет увидеть шаблон пути: [ProgramFiles64Folder][Manufacturer][ProductName].

ProgramFiles64Folder или ProgramFilesFolder означает путь к директорию Program Files, или Program Files (x86), смотря какую платформу Вы выберите, 64-битную или 32-битную.

Параметры «Manufacturer» и «ProductName» — это переменные, которые можно настроить в окне свойств проекта установщика, после того как будет выбран корень проекта «HelloWorldAddInSetup«.

Здесь же с помощью параметра «TargetPlatform» выбирается платформа, 64-битная (x64) или 32-битная (x86), это важно и зависит от того, для какого офиса будет устанавливаться надстройка, для 64-битного или 32-битного.

Не менее важным параметром является параметр «Version«, который влияет на то, будут ли при переустановке надстройки уже существующие файлы заменены, или будет отображено сообщение, что более новая версия уже установлена. При изменении этого параметра, будет предложено автоматически изменить значение параметра «ProductCode«, сформировав новый уникальный код. Ориентируясь на этот код, установщик будет принимать решение, устанавливается ли измененная надстройка или производится попытка ещё раз установить ту же самую надстройку. Если код разный, то далее уже делается проверка номера версии устанавливаемой надстройки, выше она, уже установленной, или ниже.

Так же здесь настраивается переменная «Author«, которую тоже можно использовать в шаблоне пути выходных файлов.

Еще полезные параметры, которые будут видны при установке надстройки, это «Description» — описание надстройки и «Title» — всплывающая подсказка к надстройке.

Как можно вспомнить из раздела ручной установки надстройки, для её работы кроме файлов нужна ещё запись в системном реестре. Для программной установки записи в реестр надо правой кнопкой вызвать контекстное меню на заголовке проекта установщика, и далее из меню «View» выбрать подменю «Реестр«.

Откроется вкладка Реестра (Registry), в двух ветках которой уже будут начальные записи.

Запись в ветке реестра HKEY_CURRENT_USER означает, что настройка будет установлена только для текущего пользователя. А ветка HKEY_LOCAL_MACHINE — что надстройка будет установлена для всех пользователей операционной системы. Но, в любом случае, начальные записи не верны, поэтому раздел «[Manufacture]» можно смело удалять из обоих веток.

Далее надо решить, будет ли всё-таки устанавливаться надстройка для всех или только для текущего пользователя, и выбрать для дальнейшей работы соответствующую ветку HKEY. В этой ветке к разделу «Software» надо последовательно добавить разделы, чтобы получился следующий путь: HKEY_*SoftwareMicrosoftOfficeWordAddInsParadox.HelloWorldAddIn. Понятно, что в этом пути Word означает надстройку для приложения Microsoft Word, и если надстройка создается, например, для Excel, то за место Word надо указать Excel. А раздел с именем «Paradox.HelloWorldAddIn» это уже непосредственно сама надстройка и может быть названа как угодно по своему усмотрению, но обычно её имя строится из названия организации или автора и названия надстройки через точку.

После того как путь будет построен, в разделе «Paradox.HelloWorldAddIn» следует создать четыре параметра:

  • строковый параметр «Description»
  • строковый параметр «FriendlyName»
  • параметр DWORD (32 бита) «LoadBehavior»
  • строковый параметр «Manifest»

и заполнить их аналогично, как это описано в ручной установке надстройки. Должно получиться примерно, как на изображении ниже.

Как можно заметить, в параметре «Manifest«, в отличии от ручной настройки, указан не путь к файлам надстройки, а переменная «[TARGETDIR]«, которая автоматически выстроит путь к директорию, куда будет установлена надстройка. А какой путь выстроит эта переменная, настраивается в свойствах «Application Folder» вкладки «File System» («Файловой системы«). По умолчанию это директорий с указанным наименованием организации и наименованием имени продукта в каталоге Program Files или Program Files (x86), в зависимости от того, какая платформа была выбрана.

Ну и в общем-то для сборки установщика почти всё готово. Можно ещё сделать проверку требуемой версии Microsoft .NET Framework. Для этого надо нажать правой кнопкой мыши на заголовке проекта установщика, в нашем случае это HelloWorldAddInSetup, и из контекстного меню выбрать пункт «Свойство«, после чего появиться окно страницы свойств установщика.

В этом окне надо нажать кнопку «Предварительные требования» (Prerequisites…), которое откроет окно «Необходимые компоненты«, в котором можно выбрать нужную версию .NET Framework, используемую при создании надстройки.

Так как моим приложениям часто приходиться работать на Windows 7, то я обычно рабою с .NET Framework версии 4.5.2.

Microsoft также при создании установщика для надстроек VSTO рекомендует настроить условия запуска для обнаружения среды выполнения VSTO. Но, для непосредственной установки надстройки, это не обязательно, если Вам будет интересно, то дополнительную информацию по настройке установщика можно найти на официальном сайте Microsoft. А без этих проверок надстройка после установки просто либо заработает, если у Вас Office 2013 или выше, или не заработает, если у Вас соответственно Office ниже версии 2013.

Всё, теперь надо убедиться, что режим компиляции установлен как Release и пересобрать проект установщика. В выходном каталоге проекта установщика надстройки будут созданы два файла — HelloWorldAddInSetup.msi и setup.exe, для установки надстройки можно использовать любой из них. Устанавливаем, запускаем Word и пользуемся.

07 декабря 2020 г.

Overview

Background

Microsoft Office provides a variety of component types you could develop to extend its existing functionality or to add more useful features. These components include VBA macros, VSTO components, XLL Addons, and more.

In this sample, I will focus on creating a C# VSTO project that displays a simple ribbon.

My Stack

  • Visual Studio 2019 Community.
  • .NET Framework 4.7.2 / C#
  • Office 365, Desktop Edition.
  • Windows 10 Pro 64-bit (10.0, Build 18362)

Minimal requirements

  • Visual Studio 2015
  • Office 2013

The full source code available at GitHub

Note that the following Ribbon sample can be used for extending these Office applications: Excel, Word, Outlook, and PowerPoint.

In this post, I will use Excel as a hosting application.

Setting up the environment

  1. Open Visual Studio 2019 and create a new Excel VSTO Addin C# project.

Visual Studio Setup for Office/SharePoint

Visual Studio Setup for Office/SharePoint

In case you cannot find such a project on a Visual Studio templates list, complete the following steps:

  • Open the Visual Studio 2019 setup from the Windows Control Panel.
  • Make sure Office/SharePoint development option is selected as shown in the picture.
  1. In the generated project, open the ThisAddin.cs file:
  • ThisAddIn_Startup event handler will be called by the Excel application only once in the hosting application lifetime, during the application startup. This is the recommended place for initialization.
  • ThisAddIn_Shutdown event handler will be called by the application before it exits. Do your cleanups here.

_Note: Outlook no longer raises this event. If you have code that must run when Outlook shuts down, see this link.

 1public partial class ThisAddIn
 2{
 3    private void ThisAddIn_Startup(object sender, System.EventArgs e)
 4    {
 5    }
 6
 7    private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
 8    {
 9    }
10
11    #region VSTO generated code
12      /// summary
13      /// Required method for Designer support - do not modify
14      /// the contents of this method with the code editor.
15      /// /summary
16      private void InternalStartup()
17      {
18        this.Startup += new System.EventHandler(ThisAddIn_Startup);
19        this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
20      }
21    #endregion
22}

Testing the environment

  1. Set a breakpoint in both C#ThisAddIn_Startup and ThisAddIn_Shutdown functions.
  2. Hit F5 to run the project’s debugger. An Excel splash screen should appear and shortly after ThisAddIn_Startup breakpoint will hit.
  3. Close the Excel application, ThisAddIn_Shutdown should hit.

Adding the Ribbon

When developing a VSTO, I prefer creating the ribbon by manually creating the XML rather than using the Ribbon Designer, which covers only a subset of the OfficeFluentUI model.
You can find more explanations of the difference between using the Ribbon Designer and manually building the XML in these links: xml vs ribbon designer and xml to ribbon designer comparison.

Ribbon Controller

  1. Add a new class RibbonController implementing Microsoft.Office.Core.IRibbonExtensibility interface.
  2. Make sure to set the [ComVisible(true)] class attribute.
  3. The only function you should implement is GetCustomUI that returns the XML representation of the ribbon you wish to create.
  4. For this sample, we will create a simple button that display a message box.
 1[ComVisible(true)]
 2public class RibbonController : Microsoft.Office.Core.IRibbonExtensibility
 3{
 4    private Microsoft.Office.Core.IRibbonUI _ribbonUi;
 5
 6    public string GetCustomUI(string ribbonID) =>
 7    @"<customUI xmlns='http://schemas.microsoft.com/office/2009/07/customui'>
 8      <ribbon>
 9        <tabs>
10          <tab id='sample_tab' label='GoTask'>
11            <group id='sample_group' label='Operations'>
12              <button id='do_1' label='Do 1' size='large' getImage='OnDo1GetImage' onAction='OnDo1Click'/>
13            </group>
14          </tab>
15        </tabs>
16      </ribbon>
17      </customUI>";
18
19    public void OnLoad(Microsoft.Office.Core.IRibbonUI ribbonUI)
20    {
21        _ribbonUi = ribbonUI;
22    }
23
24    public void OnDo1Click(Microsoft.Office.Core.IRibbonControl control)
25    {
26        MessageBox.Show(Resources.Do1Action);
27    }
28
29    public Bitmap OnDo1GetImage(Microsoft.Office.Core.IRibbonControl control) => Resources.Do1_128px;
30}

The sample XML above adds the ribbon to the Excel application, which includes:

  1. A new ribbon tab labeled GoTask containing a new group labeled Operations.
  2. The group containing a button labeled Do 1 with click handler implemented in OnDo1Click function.
  3. The button displaying an image located in the Resource section.

Notes for onAction callback function:

  • It must be public and have the following signature: public void SomeName(Microsoft.Office.Core.IRibbonControl control)
  • You could use any valid name, however it must match the name provided in onAction attribute in XML.
  • For the proper initialization of the Ribbon, add OnLoad function, which will be called by the hosting application once the ribbon is ready to show.

Creating an Instance of the Controller class

Once we have the RibbonController class, we need to create the instance of it.
This is done by overriding the CreateRibbonExtensibilityObject() function in the ThisAddIn class.

1protected override IRibbonExtensibility CreateRibbonExtensibilityObject() = new RibbonController();

Running the project

  1. Hit F5 to run the project again.
  2. The Excel Application should show the ribbon with a new button.

VSTO Excel Sample ribbon with button

VSTO Excel Sample ribbon with button

Useful resources

  1. Full source code of this post in GitHub
  2. Full documentation of Ribbon XML
  3. Ribbon Designer documentation
  4. Office applications that supports VSTO Addins.

Like this post? Please share to your friends:
  • Vpr в excel как это работает
  • Vpn формула в excel
  • Vpn excel что это
  • Vowels letters in one word
  • Vowels are longer in a word