Tutorial: Compartir código entre un complemento VSTO y un complemento de Office con una biblioteca de códigos compartida

Los complementos de Visual Studio Tools para Office (VSTO) son ideales para ampliar Office y ofrecer soluciones para su empresa u otras personas. Han estado presentes durante mucho tiempo y hay miles de soluciones construidas con VSTO. Sin embargo, solo se ejecutan en Office en Windows. No se pueden ejecutar complementos vsto en Mac, en la web o en plataformas móviles.

Importante

Los complementos COM y VSTO no se admiten en el nuevo Outlook en Windows que se encuentra actualmente en versión preliminar. Estos complementos siguen siendo compatibles con el cliente de escritorio clásico de Outlook en Windows. Para obtener más información, consulte Desarrollo de complementos de Outlook para nuevas Outlook en Windows.

Los complementos de Office usan HTML, JavaScript y otras tecnologías web para crear soluciones de Office en todas las plataformas. La migración de su complemento VSTO existente a un complemento de Office es una buena forma de conseguir que su solución esté disponible en todas las plataformas.

Es posible que quiera conservar el complemento VSTO y un nuevo complemento de Office con la misma funcionalidad. Esto le permite seguir atendiendo a los clientes que usan el complemento VSTO en Office en Windows. Esto también le permite ofrecer la misma funcionalidad en un complemento de Office para los clientes en todas las plataformas. También puede Hacer que su complemento de Office sea compatible con el complemento VSTO existente.

Sin embargo, es mejor evitar volver a escribir todo el código del complemento vsto para el complemento de Office. Este tutorial muestra cómo evitar la reescritura de código al usar una biblioteca de código compartida para ambos complementos.

Biblioteca de código compartida

Este tutorial le guiará por los pasos para identificar y compartir código común entre el complemento vsto y un complemento de Office moderno. Usa un ejemplo de complemento VSTO muy sencillo para los pasos para que pueda centrarse en las aptitudes y técnicas que necesitará para trabajar con sus propios complementos de VSTO.

El siguiente diagrama muestra cómo funciona la biblioteca de código compartida para la migración. El código común se refactoriza en una nueva biblioteca de código compartida. El código puede permanecer escrito en el lenguaje original, como C# o VB. Esto significa que puede seguir usando el código en el complemento VSTO existente creando una referencia de proyecto. Cuando cree el complemento de Office, también usará la biblioteca de código compartida llamándola a través de las API de REST.

Diagrama de complemento VSTO y complemento de Office con una biblioteca de código compartida.

Aptitudes y técnicas de este tutorial:

  • Crear una biblioteca de clases compartida al refactorizar el código en una biblioteca de clases .NET.
  • Crear un contenedor de API de REST con ASP.NET Core para la biblioteca de clases compartida.
  • Llamar a la API de REST desde el complemento de Office para tener acceso al código compartido.

Requisitos previos

Para configurar el entorno de desarrollo:

  1. Instale Visual Studio 2019.
  2. Instale las siguientes cargas de trabajo.
    • Desarrollo web y ASP.NET
    • Desarrollo multiplataforma de .NET Core
    • Desarrollo de Office/SharePoint
    • Los siguientes componentes individuales.
      • Visual Studio Tools para Office (VSTO)
      • Runtime de .NET Core 3.0

También necesitará lo siguiente:

El complemento VSTO analizador de celdas

Este tutorial usa la solución PnP de biblioteca compartida de complementos VSTO para complementos de Office. La carpeta /start contiene la solución de complemento de VSTO que va a migrar. El objetivo es migrar el complemento VSTO a un complemento moderno de Office compartiendo el código siempre que sea posible.

Nota:

El ejemplo usa C#, pero puede aplicar las técnicas de este tutorial a un complemento de VSTO escrito en cualquier lenguaje .NET.

  1. Descargue la solución PnP de biblioteca compartida de complementos VSTO para complementos de Office en una carpeta de trabajo de su equipo.
  2. Inicie Visual Studio 2019 y abra la solución /start/Cell-Analyzer.sln.
  3. En el menú Depurar, elija Iniciar depuración.

El complemento es un panel de tareas personalizado para Excel. Puede seleccionar cualquier celda que contenga texto y elegir el botón Mostrar Unicode. En la sección Resultado, el complemento mostrará una lista de cada carácter en el texto junto con su número de Unicode correspondiente.

El complemento VSTO de Cell Analyzer que se ejecuta en Excel con el botón

Analizar tipos de código en el complemento VSTO

La primera técnica que debe aplicarse es analizar el complemento para ver que partes del código se pueden compartir. En general, el proyecto se dividirá en tres tipos de código.

Código de UI

El código de UI interactúa con el usuario. En VSTO, el código de la interfaz de usuario funciona con Windows Forms. Los complementos de Office usan HTML, CSS y JavaScript para la interfaz de usuario. Debido a estas diferencias, no puede compartir código de interfaz de usuario con el complemento de Office. La interfaz de usuario tendrá que volver a crearse en JavaScript.

Código de documento

En VSTO, el código interactúa con el documento a través de objetos .NET, como Microsoft.Office.Interop.Excel.Range. Sin embargo, los complementos de Office usan la biblioteca de Office.js. Aunque son similares, no son exactamente iguales. Por lo tanto, de nuevo, no puede compartir el código de interacción del documento con el complemento de Office.

Código lógico

La lógica empresarial, los algoritmos, las funciones auxiliares y los códigos similares suelen componer la base de un complemento VSTO. Este código funciona independientemente de la interfaz de usuario y el código de documento para realizar análisis, conectar con servicios de back-end, ejecutar cálculos y mucho más. Este es el código que se puede compartir para que no tenga que volver a escribirlo en JavaScript.

Vamos a examinar el complemento VSTO. En el código siguiente, cada sección se identifica como código de documento, interfaz de usuario o algoritmo.

// *** UI CODE ***
private void btnUnicode_Click(object sender, EventArgs e)
{
    // *** DOCUMENT CODE ***
    Microsoft.Office.Interop.Excel.Range rangeCell;
    rangeCell = Globals.ThisAddIn.Application.ActiveCell;

    string cellValue = "";

    if (null != rangeCell.Value)
    {
        cellValue = rangeCell.Value.ToString();
    }

    // *** ALGORITHM CODE ***
    //convert string to Unicode listing
    string result = "";
    foreach (char c in cellValue)
    {
        int unicode = c;

        result += $"{c}: {unicode}\r\n";
    }

    // *** UI CODE ***
    //Output the result
    txtResult.Text = result;
}

Con este enfoque, puede ver que una sección del código se puede compartir con el complemento de Office. El código siguiente debe refactorizarse en una biblioteca de clases independiente.

// *** ALGORITHM CODE ***
//convert string to Unicode listing
string result = "";
foreach (char c in cellValue)
{
    int unicode = c;

    result += $"{c}: {unicode}\r\n";
}

Crear una biblioteca de clases compartida

Los complementos VSTO se crean en Visual Studio como proyectos .NET, por lo que volveremos a usar .NET en la medida de lo posible para simplificar las cosas. Nuestra siguiente técnica consiste en crear una biblioteca de clases y refactorizar el código compartido en esa biblioteca de clases.

  1. Si aún no lo ha hecho, inicie Visual Studio 2019 y abra la solución \start\Cell-Analyzer.sln.

  2. Haga clic con el botón derecho (o seleccione y mantenga presionada) la solución en el Explorador de soluciones y elija Agregar > nuevo proyecto.

  3. En el cuadro de diálogo Agregar un nuevo proyecto, elija Biblioteca de clases (.NET Framework) y elija Siguiente.

    Nota:

    No use la biblioteca de clases de .NET Core porque no funcionará con el proyecto de VSTO.

  4. En el cuadro de diálogo Configurar el nuevo proyecto, configure los campos siguientes.

    • Establezca el Nombre del proyecto en CellAnalyzerSharedLibrary.
    • Deje la ubicación en su valor predeterminado.
    • Configure el Marco en 4.7.2.
  5. Seleccione Crear.

  6. Una vez creado el proyecto, cambie el nombre del archivo Class1.cs a CellOperations.cs. Se mostrará un mensaje para cambiar el nombre de la clase. Cambie el nombre de la clase para que coincida con el nombre del archivo.

  7. Agregue el código siguiente a la clase CellOperations para crear un método denominado GetUnicodeFromText.

    public class CellOperations
    {
        static public string GetUnicodeFromText(string value)
        {
            string result = "";
            foreach (char c in value)
            {
                int unicode = c;
    
                result += $"{c}: {unicode}\r\n";
            }
            return result;
        }
    }
    

Usar la biblioteca de clases compartida en el complemento VSTO

Ahora necesita actualizar el complemento VSTO para usar la biblioteca de clases. Es importante que tanto el complemento VSTO como el complemento de Office usen la misma biblioteca de clases compartida, para que las futuras correcciones de errores o características se realicen en una sola ubicación.

  1. En el Explorador de soluciones, haga clic con el botón derecho (o mantenga presionado) el proyecto Cell-Analyzer y elija Agregar referencia.

  2. Seleccione CellAnalyzerSharedLibrary y haga clic en Aceptar.

  3. En el Explorador de soluciones, expanda el proyecto Cell-Analyzer , haga clic con el botón derecho (o seleccione y mantenga presionado) el archivo CellAnalyzerPane.cs y elija Ver código.

  4. En el método btnUnicode_Click, elimine las siguientes líneas de código.

    //Convert to Unicode listing
    string result = "";
    foreach (char c in cellValue)
    {
      int unicode = c;
      result += $"{c}: {unicode}\r\n";
    }
    
  5. Actualice la línea de código en el comentario //Output the result como se muestra a continuación:

    //Output the result
    txtResult.Text = CellAnalyzerSharedLibrary.CellOperations.GetUnicodeFromText(cellValue);
    
  6. En el menú Depurar, elija Iniciar depuración. El panel de tareas personalizado debería funcionar según lo previsto. Escriba texto en una celda y compruebe que pueda convertirlo en una lista Unicode con el complemento.

Crear un contenedor de API de REST

El complemento VSTO puede usar la biblioteca de clases compartida directamente, ya que ambos son proyectos .NET. Sin embargo, el complemento de Office no puede usar .NET, ya que usa JavaScript. A continuación, creará un contenedor de API REST. Esto permite que el complemento de Office llame a una API de REST, que luego pasa la llamada a la biblioteca de clases compartida.

  1. En el Explorador de soluciones, haga clic con el botón derecho (o mantenga presionado) el proyecto Cell-Analyzer y elija Agregar > nuevo proyecto.

  2. En el cuadro de diálogo Agregar un nuevo proyecto, elija Aplicación Web ASP.NET Core y elija Siguiente.

  3. En el cuadro de diálogo Configurar el nuevo proyecto, configure los campos siguientes.

    • Establezca el Nombre del proyecto en CellAnalyzerRESTAPI.
    • En el campo Ubicación, deje el valor predeterminado.
  4. Seleccione Crear.

  5. En el cuadro de diálogo Crear una nueva aplicación web ASP.NET Core, seleccione ASP.NET Core 3.1 para la versión y seleccione API en la lista de proyectos.

  6. Deje los otros campos en los valores predeterminados y elija el botón Crear.

  7. Una vez creado el proyecto, expanda el proyecto CellAnalyzerRESTAPI en el Explorador de soluciones.

  8. Haga clic con el botón derecho (o seleccione y mantenga presionado) Dependencias y elija Agregar referencia.

  9. Seleccione CellAnalyzerSharedLibrary y haga clic en Aceptar.

  10. Haga clic con el botón derecho (o seleccione y mantenga presionada) la carpeta Controladores y elija Agregar > controlador.

  11. En el cuadro de diálogo Agregar nuevo elemento con scaffolding , elija Controlador de API - Vacío y, a continuación, elija Agregar.

  12. En el cuadro de diálogo Agregar controlador de API vacío , asigne al controlador el nombre AnalyzeUnicodeController y, a continuación, elija Agregar.

  13. Abra el archivo AnalyzeUnicodeController.cs y agregue el código siguiente como método para la clase AnalyzeUnicodeController.

    [HttpGet]
    public ActionResult<string> AnalyzeUnicode(string value)
    {
      if (value == null)
      {
        return BadRequest();
      }
      return CellAnalyzerSharedLibrary.CellOperations.GetUnicodeFromText(value);
    }
    
  14. Haga clic con el botón derecho (o mantenga presionado) el proyecto CellAnalyzerRESTAPI y elija Establecer como proyecto de inicio.

  15. En el menú Depurar, elija Iniciar depuración.

  16. Se iniciará un explorador. Escriba la dirección URL siguiente para comprobar si la API de REST está funcionando: https://localhost:<ssl port number>/api/analyzeunicode?value=test. Puede volver a usar el número de puerto de la dirección URL en el explorador que Visual Studio ha iniciado. Debería ver una cadena devuelta con valores Unicode para cada carácter.

Crear el complemento de Office

Cuando cree el complemento de Office, realizará una llamada a la API de REST. Pero, en primer lugar, necesita obtener el número de puerto del servidor de la API de REST y guardarlo para más tarde.

Guardar el número de puerto SSL

  1. Si aún no lo ha hecho, inicie Visual Studio 2019 y abra la solución \start\Cell-Analyzer.sln.
  2. En el proyecto CellAnalyzerRESTAPI, expanda Propiedades y abra el archivo launchSettings.json.
  3. Busque la línea de código con el valor sslPort, copie el número de puerto y guárdelo.

Agregar el proyecto de complemento de Office

Para simplificar las cosas, conserve todo el código en una solución. Agregue el proyecto de complemento de Office a la solución de Visual Studio existente. Sin embargo, si está familiarizado con el generador de Yeoman para complementos de Office y Visual Studio Code, también puede ejecutar yo office para compilar el proyecto. Los pasos son muy similares.

  1. En el Explorador de soluciones, haga clic con el botón derecho (o mantenga presionada) la solución Cell-Analyzer y elija Agregar > nuevo proyecto.
  2. En el cuadro de diálogo Agregar un nuevo diálogo de proyecto, elija Complemento web de Excel y elija Siguiente.
  3. En el cuadro de diálogo Configurar el nuevo proyecto, configure los campos siguientes.
    • Establezca el Nombre del proyecto en CellAnalyzerOfficeAddin.
    • Deje la ubicación en su valor predeterminado.
    • Establezca el Marco en 4.7.2 o posterior.
  4. Seleccione Crear.
  5. En el cuadro de diálogo Elija el tipo de complemento, seleccione Agregar nuevas funcionalidades a Excel y elija Finalizar.

Se crearán dos proyectos:

  • CellAnalyzerOfficeAddin: este proyecto configura los archivos XML de manifiesto que describe el complemento para que Office pueda cargarlos correctamente. Contiene el ID., el nombre, la descripción y otra información sobre el complemento.
  • CellAnalyzerOfficeAddinWeb: este proyecto contiene recursos web para el complemento, como HTML, CSS y scripts. También configura una instancia de IIS Express para hospedar el complemento como una aplicación web.

Agregar la interfaz de usuario y la funcionalidad al complemento de Office

  1. En el Explorador de soluciones, expanda el proyecto CellAnalyzerOfficeAddinWeb.

  2. Abra el archivo Home.html y reemplace el contenido de <body> con el siguiente HTML.

    <button id="btnShowUnicode" onclick="showUnicode()">Show Unicode</button>
    <p>Result:</p>
    <div id="txtResult"></div>
    
  3. Abra el archivo Home.js y reemplace todo el contenido con el código siguiente.

    (function () {
      "use strict";
      // The initialize function must be run each time a new page is loaded.
      Office.initialize = function (reason) {
        $(document).ready(function () {
        });
      };
    })();
    
    function showUnicode() {
      Excel.run(function (context) {
        const range = context.workbook.getSelectedRange();
        range.load("values");
        return context.sync(range).then(function (range) {
          const url = "https://localhost:<ssl port number>/api/analyzeunicode?value=" + range.values[0][0];
          $.ajax({
            type: "GET",
            url: url,
            success: function (data) {
              let htmlData = data.replace(/\r\n/g, '<br>');
              $("#txtResult").html(htmlData);
            },
            error: function (data) {
                $("#txtResult").html("error occurred in ajax call.");
            }
          });
        });
      });
    }
    
  4. En el código anterior, escriba el número de sslPort que guardó anteriormente del archivo launchSettings.json.

En el código anterior, la cadena devuelta se procesará para reemplazar las fuentes de línea de retorno de carro por <br> etiquetas HTML. En ocasiones, puede que se encuentre en situaciones en las que un valor devuelto que funciona perfectamente para .NET en el complemento VSTO tendrá que ajustarse en el complemento de Office para funcionar correctamente. En este caso, la API REST y la biblioteca de clases compartidas solo se ocupan de devolver la cadena. La función showUnicode() es responsable de dar formato a los valores devueltos correctamente para la presentación.

Permitir CORS desde el complemento de Office

La biblioteca Office.js requiere CORS en las llamadas salientes, como la que se ha realizado desde la llamada ajax al servidor de la API de REST. Siga los pasos que se indican a continuación para permitir las llamadas entre el complemento de Office y la API de REST.

  1. En el Explorador de soluciones, seleccione el proyecto CellAnalyzerOfficeAddinWeb.

  2. En el menú Ver , elija Ventana propiedades, si aún no se muestra la ventana.

  3. En la ventana de propiedades, copie el valor de la propiedad Dirección URL de SSL y guárdelo. Esta es la dirección URL que necesita permitir a través de CORS.

  4. En el proyecto CellAnalyzerRESTAPI, abra el archivo Startup.cs.

  5. Agregue el siguiente código en la parte superior del método ConfigureServices. Asegúrese de sustituir la URL de SSL copiada anteriormente por la llamada builder.WithOrigins.

    services.AddCors(options =>
    {
      options.AddPolicy(MyAllowSpecificOrigins,
      builder =>
      {
        builder.WithOrigins("<your URL SSL>")
        .AllowAnyMethod()
        .AllowAnyHeader();
      });
    });
    

    Nota:

    Deje el / final de la dirección URL al usarla en el método builder.WithOrigins. Por ejemplo, debería ser similar a https://localhost:44000. De lo contrario, obtendrá un error cors en tiempo de ejecución.

  6. Agregue el campo siguiente a la clase Startup:

    readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
    
  7. Agregue el código siguiente al método configure inmediatamente antes de la línea de código para app.UseEndpoints.

    app.UseCors(MyAllowSpecificOrigins);
    

Cuando haya finalizado, su clase de Startup debe tener un aspecto similar al código siguiente (es posible que la dirección URL de localhost sea diferente).

public class Startup
{
  public Startup(IConfiguration configuration)
    {
      Configuration = configuration;
    }

    readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

    public IConfiguration Configuration { get; }

    // NOTE: The following code configures CORS for the localhost:44397 port.
    // This is for development purposes. In production code, you should update this to 
    // use the appropriate allowed domains.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy(MyAllowSpecificOrigins,
            builder =>
            {
                builder.WithOrigins("https://localhost:44397")
                .AllowAnyMethod()
                .AllowAnyHeader();
            });
        });
        services.AddControllers();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthorization();

        app.UseCors(MyAllowSpecificOrigins);

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

Ejecutar el complemento

  1. En el Explorador de soluciones, haga clic con el botón derecho (o mantenga presionado) el nodo superior Solución "Cell-Analyzer" y elija Establecer proyectos de inicio.

  2. En el cuadro de diálogo Páginas de propiedades de la solución 'Cell-Analyzer', seleccione Varios proyectos de inicio.

  3. Configure la propiedad Acción en Inicio para cada uno de los siguientes proyectos.

    • CellAnalyzerRESTAPI
    • CellAnalyzerOfficeAddin
    • CellAnalyzerOfficeAddinWeb
  4. Elija Aceptar.

  5. En el menú Depurar, elija Iniciar depuración.

Excel se ejecutará y realizará la carga del complemento de Office. Puede comprobar que el servicio de API de REST localhost está funcionando correctamente. Para ello, escriba un valor de texto en una celda y elija el botón Mostrar Unicode en el complemento de Office. Debería llamar a la API de REST y mostrar los valores Unicode de los caracteres de texto.

Publicar en un Azure App Service

En algún momento, querrá publicar el proyecto de API de REST en la nube. En los siguientes pasos se mostrará cómo publicar el proyecto CellAnalyzerRESTAPI en un Microsoft Azure App Service. Vea Requisitos previos para obtener información sobre cómo obtener una cuenta de Azure.

  1. En el Explorador de soluciones, haga clic con el botón derecho (o mantenga presionado) el proyecto CellAnalyzerRESTAPI y elija Publicar.
  2. En el cuadro de diálogo Elegir un destino de publicación, seleccione Crear nuevo y elija Crear perfil.
  3. En el cuadro de diálogo App Service , seleccione la cuenta correcta, si aún no está seleccionada.
  4. Se establecerán los valores predeterminados para la cuenta en los campos del cuadro de diálogo Servicio de aplicaciones. Por lo general, los valores predeterminados funcionan bien, pero puede cambiarlos si prefiere una configuración diferente.
  5. En el cuadro de diálogo Servicio de aplicaciones, elija Crear.
  6. El nuevo perfil se mostrará en una página Publicar. Elija Publicar para crear e implementar el código en el servicio de aplicaciones.

Ya puede probar el servicio. Abra un explorador y escriba una dirección URL que vaya directamente al nuevo servicio. Por ejemplo, use https://<myappservice>.azurewebsites.net/api/analyzeunicode?value=test, donde myappservice es el nombre único que creó para la nueva instancia de App Service.

Usar el Azure App Service desde el complemento de Office

El paso final consiste en actualizar el código en el complemento de Office para usar el Azure App Service en lugar de localhost.

  1. En el Explorador de soluciones, expanda el proyecto CellAnalyzerOfficeAddinWeb y abra el archivo Home.js.

  2. Cambie la constante url para que use la URL del Azure App Service, como se muestra en la siguiente línea de código. Reemplace <myappservice> por el nombre único que creó para el nuevo servicio de aplicaciones.

    const url = "https://<myappservice>.azurewebsites.net/api/analyzeunicode?value=" + range.values[0][0];
    
  3. En el Explorador de soluciones, haga clic con el botón derecho (o mantenga presionado) el nodo superior Solución "Cell-Analyzer" y elija Establecer proyectos de inicio.

  4. En el cuadro de diálogo Páginas de propiedades de la solución 'Cell-Analyzer', seleccione Varios proyectos de inicio.

  5. Habilite la acción Iniciar para cada uno de los siguientes proyectos.

    • CellAnalyzerOfficeAddinWeb
    • CellAnalyzerOfficeAddin
  6. Elija Aceptar.

  7. En el menú Depurar, elija Iniciar depuración.

Excel se ejecutará y realizará la carga del complemento de Office. Para comprobar que el servicio de aplicaciones está funcionando correctamente, escriba un valor de texto en una celda y elija Mostrar Unicode en el complemento de Office. Debería llamar al servicio y mostrar los valores Unicode de los caracteres de texto.

Conclusión

En este tutorial, ha aprendido a crear un complemento de Office que usa código compartido con el complemento VSTO original. Aprendió a conservar el código VSTO para Office en Windows y un complemento de Office para Office en otras plataformas. Refactorizó el código C# VSTO en una biblioteca compartida y lo implementó en un Azure App Service. Ha creado un complemento de Office que usa la biblioteca compartida para que no tenga que volver a escribir el código en JavaScript.