¿Por qué hacer esta integración?

Dada la buena aceptación que está teniendo nuestra entrada sobre cómo integrar la API de Google Calendars nos hemos propuesto traeros hoy un nuevo post sobre otra de las APIs de Google, en este caso de Google Sheets. Si has llegado hasta aqui, sabrás que se trata de la herramienta para crear hojas de cálculo de la suite de Google en la nube.

Como ya hemos comentado en otros posts de nuestro blog, en ocasiones suele resultar mucho más rentable integrar aplicaciones de terceros que crearla nosotros de cero, pero en el caso de Google Sheets, además nos abre un mundo de posibilidades ya que tenemos a nuestra disposición la oportunidad de leer y escribir en hojas de cálculo a través de la API de Google.

La API de Google es de las más completas y además de uso gratuito en el caso de hacer un uso privado y si no necesitamos grandes cantidades de peticiones. Además, nos provee de paquetes o SDKs para los lenguajes más usados que nos ayudarán mucho en la integración.

Comencemos

Este artículo va dirigido a aquellas personas que tienen conocimientos en el framework Laravel, por lo que ni se compartirá la totalidad del código, ni se darán grandes detalles de todo el proceso. Si lo que buscas es una empresa experta que te ayude con tu proyecto, contacta con nosotros

Configuración de la API

El proceso para habilitar la API será bastante parecido al que seguimos en la integración de la Api de Google Calendars, deberemos tener una cuenta en Google Cloud, crear un proyecto (si aún no lo hicimos) e iremos a habilitar la API de Google Sheets y la API de Google Drive, lo que nos dará acceso a leer y escribir en hojas de calculo además de ver los archivos disponibles en nuestra cuenta de Google.

Los siguientes pasos de configuración van encaminados a la pantalla de consentimiento y credenciales y no habrá que hacerlo si ya lo hicimos al habilitar otra API para el proyecto de Google Cloud:

Una vez habilitada, debemos de configurar la pantalla de consentimiento, en el que deberemos de elegir entre dos opciones:

  • Uso Interno: Donde solo harán uso de ésta, miembros de tu misma organización (cuentas de Google Workspace).

  • Uso Externo: Donde cualquiera puede hacer uso de ésta, pero ojo, Google tendrá que verificar el buen uso que estamos haciendo de ella a la hora de publicarla. Mientras desarrollamos, bastará con añadir usuarios de prueba.

Permisos: Podremos elegir los endpoints a los que accederemos.

Usuario de pruebas: Para el desarrollo.

A continuación, debemos de crear una credencial para esta API de tipo clientes OAuth 2.0, cuya principal configuración será URI de redireccionamiento autorizados, que será donde se nos redireccionará una vez que el usuario dé su consentimiento. Esta redirección vendrá con algunos parámetros entre ellos un código que nos servirá para crear los tokens de acceso a la API. Una vez creado podremos descargar nuestra credencial en formato json que guardaremos para hacer uso de él más tarde.

¡Hora de desarrollar!

En nuestro caso consumiremos la API desde una aplicación construida con Laravel, por lo que haremos uso del paquete que nos proporciona Google para el lenguaje PHP. google/apiclient Esta librería nos ayudará a integrar muchas de las APIs de la plataforma.

Llegado a este punto, es hora de ponerse a picar código.

En algún momento deberemos de solicitar al usuario que dé consentimiento de acceso a su información es momento de crear un cliente y redirigir a la AuthUrl.

public  function  getConsent()
{
   $this->client =  new Google\Client();
   $this->client->setApplicationName('Sheets');
   $this->client->setScopes($scopes);
   $this->client->setAuthConfig(base_path().'/client_secret.json'); // este archivo client es el de creadenciales que descargamos anteriormente
   $this->client->setAccessType('offline');
   $this->client->setPrompt('select_account consent');
   $authUrl =  $this->client->createAuthUrl();
   return  redirect()->to($authUrl);
}

Como vemos, necesitamos meter nuestro archivo client_secret.json en el proyecto para hacer uso de él.

Una vez que de su consentimiento para usar nuestros archivos de Drive, será redirigido a un endpoint que prepararemos para recoger el código que usaremos para crear nuestro token de acceso y poder seguir consumiendo la API.


public  function  storeToken(Request $request)
{
   $scopes =  array([\Google_Service_Drive::DRIVE);
   $this->client =  new  Client();
   $this->client->setApplicationName('Nombre Aplicación creada en cloud');
   $this->client->setScopes($scopes);
   $this->client->setAuthConfig(base_path().'/client_secret.json');
   $this->client->setAccessType('offline');
   $this->client->setPrompt('select_account consent');

   $code = $request->only('code');

   $token =  $this->client->fetchAccessTokenWithAuthCode($code['code']);

   GoogleToken::updateOrCreate(['token_type'  => $token['token_type']], $token);
}

En este caso estamos recogiendo nuestro código, generamos un nuevo token y lo guardamos en base de datos para futuros usos.

Ahora ya podemos acceder a las hojas de cálculo de nuestro usuario en Drive. Lo primero será listar las hojas disponibles, para lo que haremos uso del Servicio de drive que nos provee el SDK de Google.

public function getSheets()
    {
        $drive = new \Google_Service_Drive($this->client);
        $sheetsList = $drive->files->listFiles([
	    'q' => "mimeType='application/vnd.google-apps.spreadsheet'",
	    'fields' => 'nextPageToken, files(id, name)'
        ]);
        return $sheetsList;
    }

En este caso no mostraremos cómo crear un nuevo cliente de la API, puesto que ya lo mostramos en el primer código. Una vez creado, se lo pasaremos al Servicio de Drive y accederemos a la lista de archivos de esta manera tan sencilla indicando el tipo de archivo. En la documentación de la API encontraremos los distintos tipos que podremos obtener.

Ya tenemos un listado de las hojas, lo siguiente sería obtener la información de una de ellas:

public function getSheet($id)
    {
        $service = new \Google_Service_Sheets($this->client);
        $sheet = $service->spreadsheets->get($id, ['includeGridData' => true]);
        return $sheet;
    }

En esta función le pasaremos el identificador que hemos obtenido en el listado anterior y usando el servicio de "Sheets" nos devolverá toda la información de esta, y de cada hoja que contenga para así poder consultar después las columnas que deseemos.

A continuación el siguiente paso es leer los datos que contiene una hoja para lo que implementaremos la siguiente función:

function getValues($sheet_id, $scope)
    {
        $service = new \Google_Service_Sheets($this->client);
        $result = $service->spreadsheets_values->get($sheet_id, $scope);
        try{
        $numRows = $result->getValues() != null ? count($result->getValues()) : 0;
        // printf("%d rows retrieved.", $numRows);
        return $result;
    }
        catch(Exception $e) {
            // TODO(developer) - handle error appropriately
            echo 'Message: ' .$e->getMessage();
        }
    }

A destacar de esta función: Le pasamos 2 parámetros, el identificador del archivo y el alcance, rango o "scope" el cual llevará un patrón tipo "Nombre_Hoja!A1:D2" y marcará todo lo que debe leer, si ponemos como rango "<Nombre de la hoja>" no leerá todo el contenido. Para aprender más sobre de los rangos podemos visitar el siguiente enlace.

Esta función nos devolverá un array de arrays donde el array padre corresponde a las filas y el hijo de este a las celdas o columnas.

Por supuesto no podíamos acabar este post sin explicar cómo podemos escribir en la hoja, para lo cual podemos implementar una función como la siguiente:

// con valueInputOption en "RAW" sólo se insertan cadenas, si ponemos USER_ENTERED se analiza si es formula, fecha, etc.
    function updateValues($spreadsheetId, $range, $valueInputOption = "RAW")
    {
        try{
            $values = [
                [4, 3, 2, 1],
                [1, 2, 3, 4]
            ];

            $body = new \Google_Service_Sheets_ValueRange([
                'values' => $values
            ]);
            $params = [
                'valueInputOption' => $valueInputOption
            ];
            //executing the request
            $result = $service->spreadsheets_values->update($spreadsheetId, $range,
            $body, $params);
            // printf("%d cells updated.", $result->getUpdatedCells());
            return $result;
        } catch(Exception $e) {
            // TODO(developer) - handle error appropriately
            echo 'Message: ' .$e->getMessage();
        }
    }

Lo más destacable en esta función es que tendremos que construir el "body" de la petición usando el servicio "Google_Service_Sheets_ValueRange" y pasándole el array de arrays con los valores, como parámetros deberemos indicarle el parámetro valueInputOption que nos permitirá indicarle cómo debe interpretar los valores (como cadena, o como fórmulas)

En la documentación de la API podremos encontrar más información sobre esta API.

Conclusiones

Si lo que buscas es una empresa profesional y con gran experiencia en este tipo de integraciones, contacta con nosotros y estaremos encantados de atenderle y ayudarte en todo lo que podamos.