65.9K
CodeProject 正在变化。 阅读更多。
Home

Visual Studio Tools for Office 2008 包含 XLINQ for Yahoo 的 Ribbon 设计器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.20/5 (6投票s)

2007 年 11 月 28 日

CPOL

6分钟阅读

viewsIcon

83256

downloadIcon

1683

查看 Visual Studio 2008 中的新功能区设计器,它允许您以图形方式创建 Office 插件的功能区。从 Yahoo 图片搜索 API 添加图片,并分析文档内容。

Screenshot - 2_-_Copy.jpg

引言

在本文中,我将向您展示 Visual Studio Tools for Office、XLINQ、..NETframework v3.5 和 Visual Studio 2008 Professional 中的新功能区设计器的一些基本功能。最终产品将是一个 Microsoft Word 2007 插件,它允许用户直接通过自定义任务窗格将图片从 Yahoo 图片添加到他们的文档中,并查找文档中的关键字。将使用 Yahoo REST Web 服务,并使用 XLINQ 查询 XML 结果。功能区设计器将用于向功能区添加按钮。

Visual Studio Tools for Office 是 Visual Studio 2008 Professional 的一部分,它允许开发人员使用 .NET 创建以文档为中心的解决方案,并使用托管代码与 Word、Excel、Outlook 等集成。

创建代码

要创建新的 Word 插件,请转到“新建项目”、“Office”、“2007”、“Word 插件”。

这将显示

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

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

        }


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

        #region VSTO generated code

        /// <summary />

        /// Required method for Designer support - do not modify

        /// the contents of this method with the code editor.

        /// </summary />

        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
        
        #endregion
    }
}

为了搜索 Yahoo 图片并将其添加到文档中,我们需要创建一个用户控件来放入 `CustomTaskPane`。使用 WPF 会很好,并且可以实现更灵活的 UI,但我们需要一些简单的额外代码来显示 WPF,因为 Office 需要 Windows Forms 用户控件(稍后)。我创建了一个 Windows Forms `UserControl` 并将其留空。然后我创建了一个 WPF 用户控件,并布局了一个简单的 UI,允许输入文本进行搜索,并使用 `StackPanel` 来容纳结果。

Yahoo 图片搜索API允许以 http://search.yahooapis.com/ImageSearchService/V1/imageSearch?appid=[APPID]&query=[QUERY]&start=[START] 的形式进行 REST 查询。一旦URI已经形成,我们将使用 XLINQ 来查询结果并加载到具有我们所需字段的类中。

            //Load the result as XDocument

            var xraw = XDocument.Load(uri);
            //Populate array

            var imageArray = from image in xraw.Elements().First().Elements()
                         select new YahooImage
                         {
                             Title = image.Element(
                             "{urn:yahoo:srchmi}Title").Value,

                             LargeUrl = image.Element(
                             "{urn:yahoo:srchmi}ClickUrl").Value,

                             Thumbnail = image.Element(
                             "{urn:yahoo:srchmi}Thumbnail")
                             .Element("{urn:yahoo:srchmi}Url").Value,

                             ThumbHeight = int.Parse(image.Element(
                             "{urn:yahoo:srchmi}Thumbnail")
                             .Element("{urn:yahoo:srchmi}Height").Value),

                             ThumbWidth = int.Parse(
                             image.Element("{urn:yahoo:srchmi}Thumbnail")
                             .Element("{urn:yahoo:srchmi}Width").Value),

                             Summary = image.Element(
                             "{urn:yahoo:srchmi}Summary").Value
                         };

看看 XLINQ。它使用文档的结果元素并 `select` 一个新的 Yahoo Image。但没有使用构造函数,属性在花括号之间设置。一个非常不错、可读性强的语法。**注意**命名空间 - 如果省略命名空间,它可能找不到元素!

然后我将每个缩略图添加到按钮中,并将其放置在可滚动 `StackPanel` 中,如图所示。

            //Clear old results

            stackPanel1.Children.Clear();
            foreach (var im in imageArray)
            {
                //Show image on button

                Image image = new Image();
                ImageSourceConverter isc = new ImageSourceConverter();
                image.Source = (ImageSource)isc.ConvertFromString(im.Thumbnail);

                Button b = new Button();
                b.Content = image;
                b.Width = im.ThumbWidth;
                b.Height = im.ThumbHeight;
                b.Tag = im.LargeUrl;
                b.ToolTip = im.Title + "\n\n" + im.Summary;

                b.Click += delegate(object clicked_button, RoutedEventArgs evt_args)
                    {
                        Object missing = System.Reflection.Missing.Value;
                        //On click, add image to word document

                        try
                        {
                            Globals.ThisAddIn.Application.Selection.InlineShapes.AddPicture(
                                (clicked_button as Button).Tag.ToString(),
                                ref missing, ref missing, ref missing);
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, ex.GetType().Name);
                            Globals.ThisAddIn.CustomTaskPanes.RemoveAt(0);
                        }
                    };
                stackPanel1.Children.Add(b);
            }

不幸的是,Yahoo 托管的缩略图具有有缺陷的标头,这会导致错误并阻止图片显示。为了允许即使在协议违规的情况下也能显示图片,我创建了一个 App.config 文件并将以下内容放入其中

  <system.net>
    <settings>
      <httpWebRequest useUnsafeHeaderParsing="true" />
    </settings>
  </system.net>

当一个结果被点击时,大图片被添加到文档中,使用 `Globals.ThisAddIn.Application.Selection.InlineShapes.AddPicture((clicked_button as Button).Tag.ToString(), ref missing, ref missing, ref missing)`。此方法允许默认参数,但 C# 不支持默认参数。要发送默认值,我们使用 Missing 对象的值。这在许多 Office 函数中是必需的。

右键单击解决方案资源管理器中的项目,然后单击“添加”、“新建项”、“功能区(可视化设计器)”。这将显示功能区设计器。您可以将功能区项添加到新的功能区或现有的功能区(例如,“开始”、“插入”、“页面布局”、“引用”)。要将功能区项添加到新的功能区,请单击功能区选项卡,并在属性中设置 `Label` 属性,并将 `ControlIdType` 属性更改为 `Custom`。

但是,我们想将第一个按钮添加到“插入”选项卡,因为我们将把图片插入到文档中。要做到这一点,我们需要单击选项卡,并在属性中,确保 `ControlIdType` 显示 `Office`,然后键入我们要添加的选项卡的 `OfficeId`。这可以是以下之一:

  • TabHome
  • TabInsert
  • TabPageLayoutWord
  • TabReferences
  • TabMailings
  • TabReviewWord
  • TabView
  • TabDeveloper
  • TabAddIns
  • TabOutlining
  • TabPrintPreview
  • TabBlogInsert
  • TabBlogPost
  • TabSmartArtToolsDesign
  • TabSmartArtToolsFormat
  • TabChartToolsDesign
  • TabChartToolsLayout
  • TabChartToolsFormat
  • TabPictureToolsFormat
  • TabDrawingToolsFormatClassic
  • TabWordArtToolsFormat
  • TabDiagramToolsFormatClassic
  • TabOrganizationChartToolsFormat
  • TabTextBoxToolsFormat
  • TabTableToolsDesign
  • TabTableToolsLayout
  • TabHeaderAndFooterToolsDesign
  • TabEquationToolsDesign
  • TabPictureToolsFormatClassic
  • TabInkToolsPens

Screenshot - 1_-_Copy.jpg

因此,要添加到插入选项卡,我们使用 `TabInsert`。一个组已经添加(可以在工具箱中添加更多组)。控件必须放置在组内。从控件工具箱中,添加一个按钮。由于只有一个按钮,我将其 `ControlSize` 设置为 `RibbonControlSizeLarge`,使其看起来更好。另一个值得注意的属性是 `OfficeImageId`。按钮可以没有图像、来自资源的图像,或内置的 Office 图像。要使用 Office 图像,我需要找到图像的 ID,这可以通过下载 Office 2007 Icons Gallery 从 http://www.microsoft.com/downloads/details.aspx?familyid=12b99325-93e8-4ed4-8385-74d0f7661318&displaylang=en 来完成。我选择了 OmsSlideInsert。双击按钮会弹出点击事件处理程序,在其中我们需要代码来创建自定义任务窗格并显示它。将 `ElementHost` 添加到 Windows Forms 用户控件,以承载 WPF 控件。为此,我们需要引用 WindowsFormsIntegration.dll。还添加了一个事件处理程序,用于在关闭任务窗格时,将其从内存中移除。

        private void button1_Click(object sender, RibbonControlEventArgs e)
        {
            // use a WPF control host

            ElementHost _ElementHost;
            _ElementHost
            = new ElementHost();
            _ElementHost.Child
            = new ImageSearchWpfUserControl();
            _ElementHost.Dock = System.Windows.Forms.DockStyle.Fill;

            // stick the WPF host into a user control

            WinFormsUserControl _UserControl;
            _UserControl = new WinFormsUserControl();
            _UserControl.Controls.Add(_ElementHost);

            // make the user control the custom pane

            Microsoft.Office.Tools.CustomTaskPane m_CustomTaskPane
            = Globals.ThisAddIn.CustomTaskPanes.Add(_UserControl, "Yahoo Images Searcher");

            m_CustomTaskPane.DockPosition =
Microsoft.Office.Core.MsoCTPDockPosition.msoCTPDockPositionLeft;

            m_CustomTaskPane.Visible = true;
            m_CustomTaskPane.VisibleChanged +=
                new EventHandler(m_CustomTaskPane_VisibleChanged);
        }

        void m_CustomTaskPane_VisibleChanged(object sender, EventArgs e)
        {
            Microsoft.Office.Tools.CustomTaskPane ctp =
                (sender as Microsoft.Office.Tools.CustomTaskPane);
            if (ctp.Visible == false)
            {
                Globals.ThisAddIn.CustomTaskPanes.Remove(ctp);
            }
        }

在这里,我们再次使用了出色的 `Globals` 类,该类提供了从任何代码文件中轻松访问插件和 Office 集成的能力。

Screenshot - 2_-_Copy.jpg

查看右侧的 Yahoo Images 按钮,以及 WPF 搜索结果。

下一个任务是向“审阅”选项卡(TabReviewWord)添加一个标有“关键字分析”的按钮,该按钮会将文档发送到 Yahoo 内容分析 Web 服务(尝试后发现它并不太好,但算了)以获取文档的关键字。我向功能区添加了一个新选项卡,并添加了一个包含一个按钮的组。按钮的 `OfficeImageId` 设置为 FunctionsRecentlyUsedtInsertGallery。单击按钮时,我们需要将数据发布到 Web 服务,然后迭代结果,最后显示在标准 `MessageBox` 中。要获取文档文本,我使用了 `Globals.ThisAddIn.Application.ActiveDocument.Content.Text`。通过浏览智能提示,可以找到许多其他属性和函数。下面,注意“关键字分析”按钮,可以看到 Web 服务已识别出与活动文档相关的关键字。

Screenshot - 3_-_Copy.jpg

        private void button2_Click(object sender, RibbonControlEventArgs e)
        {
            //Send query by post

            System.Net.WebClient wc = new System.Net.WebClient();
            System.Collections.Specialized.NameValueCollection nvc =
                new System.Collections.Specialized.NameValueCollection();
            nvc.Add("appid", Properties.Settings.Default.AppId);
            nvc.Add("context",
                Globals.ThisAddIn.Application.ActiveDocument.Content.Text);
            XDocument xdoc = XDocument.Parse(Encoding.UTF8.GetString(
                wc.UploadValues("http://search.yahooapis.com/ContentAnalysisService/V1/termExtraction", 
                "POST", nvc)));
            //Iterate through keywords

            StringBuilder keywords = new StringBuilder();
            foreach (var xresult in xdoc.Elements().First().Elements())
            {
                keywords.AppendLine(xresult.Value);
            }
            //Show a message box!

            System.Windows.Forms.MessageBox.Show(
                keywords.ToString(), "Keywords");
        }

这是对 Visual Studio 中新的功能区设计器等功能的快速介绍。功能区设计器还允许您向 Office 按钮添加新的菜单项,并允许您(不可逆地)将功能区导出到 XML,以实现更高级的功能,例如重新设计命令。例如,如果重新设计 `FileSave`,每当用户按下 Ctrl+S 或单击“保存”而不是打开正常的保存对话框时,您的自定义代码都可以运行。要尝试此操作,请从功能区设计器导出 XML,按照代码中的注释说明进行操作,并添加以下 XML 和 C# 代码,这将在保存之前询问用户是否真的要保存

<?xml version="1.0" encoding="UTF-8"?>
<customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<!--HERE-->
   <commands> 
     <command idMso="FileSave" onAction="doYouWantToSave" /> 
   </commands> 
<!--/HERE-->
    <ribbon>
        <tabs>
            <tab idMso="TabInsert">
                <group id="group1" label="Web">
                    <button id="button1" imageMso="OmsSlideInsert" 
onAction="button1_Click" screentip="Yahoo! Images" 
supertip="Search Yahoo! Images for images to add to your document." label="Yahoo Images" 
size="large" />
                </group>
            </tab>
            <tab idMso="TabReviewWord">
                <group id="group2" label="Analysis">
                    <button id="button2" imageMso="FunctionsRecentlyUsedtInsertGallery" 
onAction="button2_Click" 
screentip="Keyword Analysis" supertip="Find keywords in this document using Yahoo! web service" 
label="Keyword Analysis" size="large" />
                </group>
            </tab>
    </ribbon>
</customUI>

        private void doYouWantToSave(Microsoft.Office.Core.IRibbonControl control, bool cancel)
        {
            cancel = (System.Windows.Forms.MessageBox.Show("Do you really want to do FileSave?",
            "???", System.Windows.Forms.MessageBoxButtons.YesNo)
                        == System.Windows.Forms.DialogResult.OK) ? false : true;
        }

附加的代码还包含一个名为“mess”的功能区选项卡。默认情况下,其 `Visible` 设置为 `false`,但更改后,您可以看到如何将其他控件(除了按钮)添加到功能区,例如库、按钮组、切换按钮。请注意,它出现在“邮件合并”选项卡之前 - 这是由于设置了 `Position` 属性。

Screenshot - 4_-_Copy.jpg

代码 下载 WordAddIn1.zip - 132.9 KB 是可用的,它完成了展示使用 VS 2008 进行 Office 的基本集成和一些 XLINQ 的目的。请享用。有关如何使用本文或代码的简要说明。类名、方法和属性、任何技巧或提示。代码块应设置为“格式化”样式,如下所示

关注点

令人烦恼:托管在有协议违规的糟糕服务器上的缩略图。

好的:几乎您可以在 Office 中做的任何事情都有一个函数。

好的:安装方法是,转到 debug 文件夹,只需双击 WordAddIn1.vsto!简单。

重要:有很多代码/OfficeId 可供选择,但它们可以在可下载的电子表格/文档中找到。

好的:它实际上工作得相当好。

历史

2007 年 11 月 28 日 - 添加了原始文章

2007 年 11 月 30 日,2007 年 12 月 5 日 - 小幅更新

© . All rights reserved.