https://d226lax1qjow5r.cloudfront.net/blog/blogposts/make-phone-calls-with-microsoft-excel-and-vonage-open-contactpad-sdk/embed-vbc.png

Realiza llamadas telefónicas con Microsoft Excel y Vonage Open ContactPad SDK

Publicado el February 14, 2022

Tiempo de lectura: 7 minutos

Introducción

En esta página, explicaré cómo construí una integración VBC funcional con una plataforma de terceros en poco tiempo aprovechando el nuevo Vonage Open ContactPad. Primero, aquí hay un Video que demuestra la funcionalidad disponible de la integración.

Aplicaciones seleccionadas - Microsoft Excel Online

He seleccionado Microsoft Excel Online porque había leído recientemente que Microsoft había lanzado una API JavaScript para Excel. Mucha gente utiliza el programa para trabajar con hojas de cálculo y me pareció una forma razonablemente sencilla de tratar los datos. Microsoft Excel permite integraciones a través de complementos de Office. Un complemento muy interesante es Laboratorio de scriptsque permite a los desarrolladores experimentar con la creación de complementos. El alcance de este how-to será ir a través de la adición de código en Script Lab utilizando Excel y Vonage funciones JavaScript y luego publicar el resultado a un GitHub Gist. Para avanzar a partir de ahí, el lector puede estar interesado en publicación de complementos de Office.

Siguiendo en Microsoft Excel Online

Para sacar el máximo partido a este tutorial, se recomienda instalar el complemento Script Lab Office e importar la lista Gist de Github:

En Gist contiene el código fuente completo para que lo adaptes a tu proyecto. Los ejemplos que aparecen a continuación son a veces muy específicos y no incluyen todo lo necesario para ejecutar una determinada función.

Primeros pasos con Vonage Open ContactPad

En kit de desarrollo de software Vonage Open ContactPad es un kit de herramientas de desarrollo de software JavaScript que permite a los desarrolladores integrar una aplicación de comunicaciones unificadas (UC) de Vonage de Vonage en una aplicación basada en Internet. Si bien requiere iniciar sesión con Vonage Business Communications para usarlo, puedes desarrollar con el SDK sin usuarios de API ni registros adicionales. Esto lo convierte en un marco de integración muy liviano para los desarrolladores que desean incorporar clientes de comunicaciones en sus aplicaciones.

¿Por qué Microsoft Excel Online y no una aplicación para PC / Mac?

Es importante tener en cuenta que el producto Vonage Open ContactPad SDK está diseñado para ser integrado en aplicaciones web y funciona mejor cuando el desarrollador tiene control total sobre el espacio en el que está integrado. Hay una nota en la parte inferior de la página de página de inicio que hace este mismo punto.

Configuración del laboratorio de scripts y primeras líneas de código

Cuando instala Script Lab en Excel, se crea un elemento de menú Script Lab a la derecha del elemento de menú Ayuda. Haga clic en su pestaña y verá 3 botones que le ayudarán a trabajar con Script Lab: Código, Ejecutar y Funciones. A continuación, haga clic en Código, aparecerá una ventana incrustada en la interfaz de Excel con una ventana similar a VisualStudio que contendrá su código. Mientras no borre la caché de su navegador, su código de Script Lab permanecerá. Si prefieres más permanencia, utilizarás la opción Compartir para guardar tu código como un gist en GitHub. En mis aventuras, acabé creando un montón de gists privados. Si estuviera trabajando en un verdadero proyecto de integración, probablemente transferiría mi código a Visual Studio Code y trabajaría con un control de versiones más preciso.

Una vez que conseguí la disposición de la tierra en Script Lab, empecé con la sección HTML donde sabía que quería incrustar mi marcador. Para seguir adelante, echa un vistazo a las instrucciones aquí para cargar el Open ContactPad. Esto incluye un ejemplo en vivo de cómo hacerlo usando Plunker.

En mi caso, quería proporcionar un <div> para que mi aplicación apareciera en la interfaz completa del marcador y no como un punto móvil en la página. Establecí el proveedor de datos como uc para cargar el marcador de Unified Communications.

<div class="vonage-dialer-container"></div>
<script data-provider="uc" data-autoload="false" src="https://apps.gunify.vonage.com/cti/common/vonage.dialer.sdk.js">
</script>

Lo asombroso es que puede PARAR AQUÍ, ejecutar el código, ¡y tener un marcador incrustado en Microsoft Excel Online! Sin embargo, hay mucho más que los desarrolladores pueden hacer para personalizar la experiencia.

Exploración de la API de Excel - Configuración de los datos de muestra

Entonces, ¿por qué crear datos de ejemplo? Bueno, yo quería dar a los usuarios ejemplos de cómo quiero que el formato y la ubicación de los datos en la hoja de cálculo para que el código sabe dónde encontrarlo. Quería un área en la que se pudiera hacer clic para activar una llamada telefónica para cada "contacto" (fila) y establecer un lugar para un número de teléfono. Empecé con el HTML para la aplicación en Script Lab y añadí un botón que rellenaría los datos en la sección deseada de la hoja de cálculo. Si pulsas este botón varias veces, simplemente sobrescribirá lo que hay en la hoja.

<center><button onclick="populateSampleData()">Populate Sample Data</button></center>

El siguiente paso es implementar la función populateSampleData() en JavaScript. Afortunadamente, la API JavaScript de Microsoft Excel contiene algunos ejemplos.

function populateSampleData() {
 return Excel.run(function(context) {
   var worksheet = context.workbook.worksheets.getItem("Sheet1");
 
   var data = [
     ["Company", "Contact Last", "Contact First", "Number", ""],
     ["Widget Zone", "Anderson", "Wendy", "555-555-5555", "Dial"],
     ["Widgets Galore", "Burns", "Ryan", "555-555-5555", "Dial"],
     ["Widgets Emporium", "Johnson", "Amanda", "555-555-5555", "Dial"]
   ];
 
   var range = worksheet.getRange("A2:E5");
   range.values = data;
   range.format.autofitColumns();
 
   return context.sync().then(function() {});
 }).catch(errorHandlerFunction);
}

Inicialmente, se selecciona la primera hoja de cálculo, que en un fichero Excel en blanco se llama normalmente "Hoja1". A continuación, crea un objeto con los datos que van en la hoja. A continuación, establece el rango para cubrir la cantidad de celdas que ocuparán los datos y establece los valores del rango en el objeto de datos. Autoajustar las columnas hace que la apariencia sea un poco más ordenada.

También he creado un formato que se aplica cuando se carga la aplicación. Esto posiciona la selección en la celda superior izquierda. Así como, hace que mi Dial "botones" clickable y cambia su fondo y los colores del texto.

//start with selection at upper left
 var worksheet = context.workbook.worksheets.getItem("Sheet1");
 var initSelection = worksheet.getRange("A1");
 initSelection.select();
 
 //format dial buttons
 var range = worksheet.getRange("E:E");
 var conditionalFormat = range.conditionalFormats.add(Excel.ConditionalFormatType.containsText);
 
 conditionalFormat.textComparison.format.font.color = "white";
 conditionalFormat.textComparison.format.fill.color = "purple";
 conditionalFormat.textComparison.rule = {
   operator: Excel.ConditionalTextOperator.contains,
   text: "Dial"
 };

Activar el "botón" de marcación

Uno de los logros más satisfactorios de este proyecto es la posibilidad de hacer clic en algo de la hoja de Excel y activar una llamada telefónica a un número procedente de esa hoja. En mi caso, se trata del "botón" Dial que aparece en cada fila de datos. Uso "botón" entre comillas porque no es un botón en absoluto - sólo una celda con la palabra "Dial". He creado un controlador que comprueba los cambios de selección y reacciona cuando el texto de la celda pulsada coincide con la palabra "Dial".

function handleSelectionChanged(event) {
 return Excel.run(function(context) {
   var range = context.workbook.getSelectedRange().load();
 
   return context.sync().then(function() {
     const selectedContent = JSON.stringify(range.values, null, 4);
 
     const rowString = JSON.stringify(range.rowIndex, null, 4);
 
     const rowIndex = Number(rowString) + 1;
 
     if (selectedContent.match("Dial")) {
       placeCall(rowIndex);
     }
   });
 }).catch(errorHandlerFunction);
}
 
function placeCall(row) {
 return Excel.run(function(context) {
   var toNumberRange = context.workbook.worksheets
     .getItem("Sheet1")
     .getRange("D" + row)
     .load();
 
   return context.sync().then(function() {
     const toNumber = JSON.stringify(toNumberRange.values, null, 4);
 
     VonageDialer.placeCall(toNumber);
   });
 }).catch(errorHandlerFunction);
}

Cómo reaccionar ante los eventos de Vonage Communications

Otra potente función de Open ContactPad te permite hacer que sucedan cosas dentro de tu aplicación integrada en función de cuándo recibe eventos de Vonage. Todo lo que tienes que hacer es mirar el tipo de evento (event.type) y crear código para reaccionar ante el evento. Los detalles de lo que hace mi código para estos eventos se describirán en el área Temas avanzados. CALL_START, CALL_ANSWER, y CALL_END son sólo algunas de las opciones disponibles. Para más información, consulte la sección Modelos de datos del SDK.

VonageDialer.init({ /* dialer config options */ }, (dialer) => {
 dialer.setOnDialerEvent((event) => {
   switch (event.type) {
     case 'CALL_START': {
       break;
     }
     case 'CALL_ANSWER': { // available only for UC
       break;
     }
     case 'CALL_END': {
       // do something based on event.data (screen pop, store interaction, etc.)
       break;
     }
     default: {
       console.log('Unhandled event', event);
     }
  }
 });
});

Temas avanzados

En esta sección se tratarán otras personalizaciones para que la integración sea propia, como la implementación de la búsqueda de contactos y la configuración del contacto de interacción.

Implementación de la búsqueda de contactos: cuando las filas de Excel se convierten en contactos buscables

Veamos cómo hacer que los contactos de la hoja de cálculo se puedan buscar en ContactPad.

Añadir función de proveedor de contactos

Lo primero que hay que hacer para que aparezcan los contactos es habilitar la característica contactsProvider como parte de la inicialización del marcador. Como se muestra en la siguiente sección, simplemente establezca el valor a true bajo features, ¡y estará todo listo! Esta documentación tiene más información sobre la creación de un proveedor de integración.

Registrar icono SVG

Si registras un icono, se utilizará para designar visualmente de dónde proceden los contactos. Dado que se trata de una integración de Excel, he optado por utilizar el icono de Excel. Obtuve el base64 de Icono Scout.

VonageDialer.init(
 {
   features: {
     contactsProvider: true,
     openContact: true
   }
 },
 (dialer) => {
   dialer.registerSvgIcon(
     "excel",
     "data: image / svg + xml; utf8; base64, **excel icon SVG data goes here**
   );

Proporcionar los datos de contacto - Implementar los gestores

Screenshot of Microsoft Excel and the Vonage Open ContactPad with the number 55 in the Contact Number section with search results displayed belowSearch Contact Data

Aventuras en el formato de números de teléfono

Formatear, almacenar y buscar números de teléfono puede convertirse en una tarea bastante complicada. Para hacerse una idea, eche un vistazo a este artículo de SitePoint que describe la complejidad. Afortunadamente, en mi propio proyecto, tengo control sobre algunas cosas. Por un lado, sé que mi usuario sólo tiene un número de EE.UU.. Por lo tanto, he establecido explícitamente el código de país de mi marcador a EE.UU..

var countryCode = "US";
VonageDialer.setCountryCode(countryCode);

También asumo que todos los números de teléfono que se introducirán son números de EE.UU., por lo que utilizo libphonenumber con el país de EE.UU. para formatear los números tanto para la búsqueda como para la visualización.

<script src="https://unpkg.com/libphonenumber-js@1.9.6/bundle/libphonenumber-max.js">
</script>
filteredContacts.push(sortedContacts[i]);
const ph = libphonenumber.parsePhoneNumber(sortedContacts[i].phoneNumber, countryCode);

Para un ejemplo rápido, mi código es suficiente, pero dependiendo de tus objetivos con tu implementación, querrás pasar tiempo considerando los Numbers de tus usuarios, los Numbers que serán considerados contactos, e implementar tus funciones de búsqueda muy cuidadosamente.

Funciones para traducir y filtrar los datos de los contactos

Estas son las funciones que creé para traducir los datos de los contactos del formato que espera el JavaScript de Excel al formato que espera el JavaScript de Vonage. Se llaman en el código que te permite buscar los contactos.

   function translateContacts(excelData) {
     excelData = JSON.parse(excelData);
     let len = excelData.length,
       contactsData = [],
       obj = new Object(),
       objString = "",
       i;
     for (i = 0; i < len; i += 1) {
       if (excelData[i][4] == "Dial") {
         obj["provider"] = "excel";
         obj["id"] = i;
         obj["label"] = excelData[i][2] + " " + excelData[i][1] + " of " + excelData[i][0];
         obj["type"] = "Contact";
         const ph = libphonenumber.parsePhoneNumber(excelData[i][3], countryCode);
         obj["phoneNumber"] = ph.format("INTERNATIONAL").replace(/\D/g, "");
         objString = JSON.stringify(obj);
         contactsData.push(JSON.parse(objString));
       }
     }
     return contactsData;
   }
   function filterContacts(query, contacts) {
     const sortedContacts = contacts.sort(function (a, b) {
       const labelA = a.label.toUpperCase(); // ignore upper and lowercase
       const labelB = b.label.toUpperCase(); // ignore upper and lowercase
       if (labelA < labelB) {
         return -1;
       }
       if (labelA > labelB) {
         return 1;
       }
       // names must be equal
       return 0;
     });
     let filteredContacts = [];
     for (let i = 0; i < sortedContacts.length; i++) {
       if (
         JSON.stringify(Object.values(sortedContacts[i]).filter(item => item !== "excel"))
           .toUpperCase()
           .indexOf(query.toUpperCase()) > 0
       ) {
         filteredContacts.push(sortedContacts[i]);
         const ph = libphonenumber.parsePhoneNumber(sortedContacts[i].phoneNumber, countryCode);
         sortedContacts[i].phoneNumber = ph.format("INTERNATIONAL");
       }
     }
     return filteredContacts;
   }
Creación de las sugerencias de marcación
   const searchContactables = (query, callback) => {
     Excel.run(function(context) {
       var worksheet = context.workbook.worksheets.getItem("Sheet1");
 
       var range = worksheet.getRange("A3:E999");
       range.load("values");
 
       return context.sync().then(function() {
         const excelData = JSON.stringify(range.values, null, 4);
         const contactsData = translateContacts(excelData);
 
         const filteredContacts = filterContacts(query.replace(/[^A-Za-z0-9_]/g, ""), contactsData);
 
         callback(filteredContacts);
       });
     }).catch(errorHandlerFunction);
   };
   dialer.setOnSearchContactables(searchContactables);

Establecer el contacto de interacción - Mostrar los datos del contacto en la interfaz del marcador

Esta funcionalidad se describe en la sección Establecer contenido de interacción de la documentación de Open ContactPad. Aquí muestro cómo he implementado la capacidad para que la información de contacto del número remoto aparezca en el marcador durante una llamada.

Screenshot of the Code Window of the Vonage Open ContactPad interface while in a call.Dialer Interface

 dialer.setOnDialerEvent((event) => {
   //search for contact
   Excel.run(function(context) {
     var worksheet = context.workbook.worksheets.getItem("Sheet1");
     var range = worksheet.getRange("A3:E999");
     range.load("values");
     return context.sync().then(function() {
       const excelData = JSON.stringify(range.values, null, 4);
       const contactsData = translateContacts(excelData);
       const query = "" + event.data.phoneNumber;
       const filteredContacts = filterContacts(query.replace(/[^A-Za-z0-9_]/g, ""), contactsData);
       const interactionContact = filteredContacts[0];
       switch (event.type) {
         case "CALL_START": {
           if (filteredContacts.length > 0) {
             dialer.setInteractionContact(event.data.id, {
               provider: interactionContact.provider,
               id: "" + interactionContact.id,
               label: interactionContact.label,
               type: interactionContact.type
             });
           }
           break;
         }

Implantar la capacidad de "abrir" el contacto

Screenshot of Microsoft Excel and the Vonage Open ContactPad with the number 555 in the Contact Number section with search results displayed below and the first match highlighted in the Excel sheetOpen Contact

Añadir la función de contacto abierto

Este código resaltará el contacto en la hoja Excel cuando el usuario haga clic en el icono de enlace desde la búsqueda de contactos. Para que funcione requiere openContact: true en las init del marcador.

case "OPEN_CONTACT": {
     const rowNumber = event.data.id + 3;
     const rowString = "A" + rowNumber + ":D" + rowNumber;
     const row = worksheet.getRange(rowString);
     row.select();
     break;
   }
// Dialer init
VonageDialer.init({
  features: {
    contactsProvider: true,
    openContact: true,
    openActivity: 'acme',
    eventsHistory: true
  }
}, (dialer) => { /* <-- dialer instance */ });

Resumen

Espero que al leer esto, puedas crear un marcador de Vonage personalizable que pueda usarse en muchas aplicaciones diferentes. Por favor, comparte en comunicaciones empresariales-api en el canal Slack org de la comunidad de Vonage si has utilizado esta información para crear implementaciones útiles por tu cuenta.

Compartir:

https://a.storyblok.com/f/270183/400x453/37e0b25a78/lisa-venezia.png
Lisa Venezia

Lisa helps connect business communications with customer workflows by working closely with the teams that create Vonage integrations with CRMs such as Salesforce, Microsoft Dynamics and HubSpot. Through adding developer solutions for Vonage Apps, she looks forward to unlocking powerful capabilities for people to work and communicate seamlessly within the platforms they use the most. Outside of work, Lisa enjoys singing choral music, playing the mellophone bugle, and spending time with her husband and their corgi.