Interagir avec Google Sheets à partir de Java

Interagir avec Google Sheets à partir de Java

1. Vue d'ensemble

Google Sheets constitue un moyen pratique de stocker et de manipuler des feuilles de calcul et de collaborer avec d’autres sur un document.

Parfois, il peut être utile d'accéder à ces documents à partir d'une application, par exemple pour effectuer une opération automatisée. À cette fin, Google fournit l'API Google Sheets avec laquelle les développeurs peuvent interagir.

Dans cet article,we’re going to take a look at how we can connect to the API and perform operations on Google Sheets.

2. Dépendances Maven

Pour nous connecter à l'API et manipuler des documents, nous devons ajouter les dépendancesgoogle-api-client,google-oauth-client-jetty etgoogle-api-services-sheets:


    com.google.api-client
    google-api-client
    1.23.0


    com.google.oauth-client
    google-oauth-client-jetty
    1.23.0


    com.google.apis
    google-api-services-sheets
    v4-rev493-1.23.0

3. Autorisation

The Google Sheets API requires OAuth 2.0 authorization avant de pouvoir y accéder via une application.

Tout d'abord, nous devons obtenir un ensemble d'informations d'identification OAuth, puis l'utiliser dans notre application pour soumettre une demande d'autorisation.

3.1. Obtention des informations d'identification OAuth 2.0

Pour obtenir les informations d'identification, nous devons créer un projet dans leGoogle Developers Console, puis activer l'API Google Sheets pour le projet. La première étape du guideGoogle Quickstart contient des informations détaillées sur la manière de procéder.

Une fois que nous avons téléchargé le fichier JSON avec les informations d'identification, copions le contenu dans un fichiergoogle-sheets-client-secret.json dans le répertoiresrc/main/resources de notre application.

Le contenu du fichier devrait ressembler à ceci:

{
  "installed":
    {
      "client_id":"",
      "project_id":"decisive-octane-187810",
      "auth_uri":"https://accounts.google.com/o/oauth2/auth",
      "token_uri":"https://accounts.google.com/o/oauth2/token",
      "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
      "client_secret":"",
      "redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]
    }
}

3.2. Obtention d'un objetCredential

Une autorisation réussie renvoie un objetCredential que nous pouvons utiliser pour interagir avec l'API Google Sheets.

Créons une classeGoogleAuthorizeUtil avec une méthode statiqueauthorize() qui lit le contenu du fichier JSON ci-dessus et construit un objetGoogleClientSecrets.

Ensuite, nous allons créer unGoogleAuthorizationCodeFlow et envoyer la demande d'autorisation:

public class GoogleAuthorizeUtil {
    public static Credential authorize() throws IOException, GeneralSecurityException {

        // build GoogleClientSecrets from JSON file

        List scopes = Arrays.asList(SheetsScopes.SPREADSHEETS);

        // build Credential object

        return credential;
    }
}

Dans notre exemple, nous définissons l'étendue deSPREADSHEETS car nous voulons accéder à Google Sheets et utiliser unDataStoreFactory en mémoire pour stocker les informations d'identification reçues. Une autre option consiste à utiliser unFileDataStoreFactory pour stocker les informations d'identification dans un fichier.

Pour le code source complet desGoogleAuthorizeUtil class,, consultezthe GitHub project.

4. Construction de l'instance de serviceSheets

Pour interagir avec Google Sheets, nous aurons besoin dea Sheets object which is the client for reading and writing through the API.

Créons une classeSheetsServiceUtil qui utilise l’objetCredential ci-dessus pour obtenir une instance deSheets:

public class SheetsServiceUtil {
    private static final String APPLICATION_NAME = "Google Sheets Example";

    public static Sheets getSheetsService() throws IOException, GeneralSecurityException {
        Credential credential = GoogleAuthorizeUtil.authorize();
        return new Sheets.Builder(
          GoogleNetHttpTransport.newTrustedTransport(),
          JacksonFactory.getDefaultInstance(), credential)
          .setApplicationName(APPLICATION_NAME)
          .build();
    }
}

Ensuite, nous examinerons certaines des opérations les plus courantes que nous pouvons effectuer à l'aide de l'API.

5. Ecrire des valeurs sur une feuille

Pour interagir avec une feuille de calcul existante, il faut connaître l'identifiant de cette feuille de calcul, que nous pouvons trouver à partir de son URL.

Pour nos exemples, nous allons utiliser une feuille de calcul publique appelée "Dépenses", située à l'adresse suivante:

Sur la base de cette URL, nous pouvons identifier l'ID de cette feuille de calcul comme suit: "1sILuxZUnyl_7-MlNThjt765oWshN3Xs-PPLfqYe4DhI".

Aussi,to read and write values, we’re going to use spreadsheets.values collections.

Les valeurs sont représentées sous forme d'objetsValueRange, qui sont des listes de listes deObjects, Java correspondant à des lignes ou des colonnes dans une feuille.

Créons une classe de test où nous initialisons notre objet de serviceSheets et une constante SPREADSHEET_ID:

public class GoogleSheetsLiveTest {
    private static Sheets sheetsService;
    private static String SPREADSHEET_ID = // ...

    @BeforeClass
    public static void setup() throws GeneralSecurityException, IOException {
        sheetsService = SheetsServiceUtil.getSheetsService();
    }
}

Ensuite, nous pouvons écrire des valeurs en:

  • écrire sur une seule plage

  • écriture dans plusieurs gammes

  • ajout de données après une table

5.1. Ecrire dans une seule plage

Pour écrire des valeurs dans une seule plage sur une feuille, nous utiliserons la méthodespreadsheets().values().update():

@Test
public void whenWriteSheet_thenReadSheetOk() throws IOException {
    ValueRange body = new ValueRange()
      .setValues(Arrays.asList(
        Arrays.asList("Expenses January"),
        Arrays.asList("books", "30"),
        Arrays.asList("pens", "10"),
        Arrays.asList("Expenses February"),
        Arrays.asList("clothes", "20"),
        Arrays.asList("shoes", "5")));
    UpdateValuesResponse result = sheetsService.spreadsheets().values()
      .update(SPREADSHEET_ID, "A1", body)
      .setValueInputOption("RAW")
      .execute();
}

Ici, nous créons d'abord un objetValueRange avec plusieurs lignes contenant une liste de dépenses pendant deux mois.

Ensuite, nous utilisons la méthodeupdate() pour créer une requête qui écrit les valeurs dans la feuille de calcul avec l'ID donné, en commençant par la cellule "A1".

Pour envoyer la demande, nous utilisons la méthodeexecute().

Si nous voulons que nos ensembles de valeurs soient considérés comme des colonnes au lieu de lignes, nous pouvons utiliser la méthodesetMajorDimension(“COLUMNS”).

L'option d'entrée «RAW» signifie que les valeurs sont écrites exactement telles qu'elles sont et non calculées.

Lors de l'exécution de ce test JUnit,the application will open a browser window using the system’s default browser that asks the user to log in and give our application permission to interact with Google Sheets on the user’s behalf:

image

Notez que cette étape manuelle peut être contournée si vous avez unOAuth Service Account.

A requirement for the application to be able to view or edit the spreadsheet is that the signed-in user has a view or edit access to it. Sinon, la demande entraînera une erreur 403. La feuille de calcul que nous utilisons pour notre exemple est définie sur un accès en édition publique.

Maintenant, si nous vérifions la feuille de calcul, nous verrons que la plage «A1:B6» est mise à jour avec nos ensembles de valeurs.

Passons à l'écriture dans plusieurs plages disparates en une seule demande.

5.2. Écriture dans plusieurs plages

Si nous voulons mettre à jour plusieurs plages sur une feuille, nous pouvons utiliser unBatchUpdateValuesRequest pour de meilleures performances:

List data = new ArrayList<>();
data.add(new ValueRange()
  .setRange("D1")
  .setValues(Arrays.asList(
    Arrays.asList("January Total", "=B2+B3"))));
data.add(new ValueRange()
  .setRange("D4")
  .setValues(Arrays.asList(
    Arrays.asList("February Total", "=B5+B6"))));

BatchUpdateValuesRequest batchBody = new BatchUpdateValuesRequest()
  .setValueInputOption("USER_ENTERED")
  .setData(data);

BatchUpdateValuesResponse batchResult = sheetsService.spreadsheets().values()
  .batchUpdate(SPREADSHEET_ID, batchBody)
  .execute();

Dans cet exemple, nous créons d'abord une liste deValueRanges,, chacune composée de deux cellules représentant le nom du mois et le total des dépenses.

Ensuite, nous créons unBatchUpdateValuesRequest avecthe input option “USER_ENTERED”, as opposed to “RAW”, meaning the cell values will be computed based on the formula d'ajout de deux autres cellules.

Enfin, nous créons et envoyons la requêtebatchUpdate. En conséquence, les plages «D1:E1» et «D4:E4» seront mises à jour.

5.3. Ajout de données après un tableau

Une autre façon d'écrire les valeurs dans une feuille consiste à les ajouter à la fin d'un tableau.

Pour cela, nous pouvons utiliser la méthodeappend():

ValueRange appendBody = new ValueRange()
  .setValues(Arrays.asList(
    Arrays.asList("Total", "=E1+E4")));
AppendValuesResponse appendResult = sheetsService.spreadsheets().values()
  .append(SPREADSHEET_ID, "A1", appendBody)
  .setValueInputOption("USER_ENTERED")
  .setInsertDataOption("INSERT_ROWS")
  .setIncludeValuesInResponse(true)
  .execute();

ValueRange total = appendResult.getUpdates().getUpdatedData();
assertThat(total.getValues().get(0).get(1)).isEqualTo("65");

Tout d'abord, nous construisons l'objetValueRange contenant les valeurs de cellule que nous voulons ajouter.

Dans notre cas, cela contient une cellule avec les dépenses totales pour les deux mois que nous trouvons en ajoutant les valeurs de cellule“E1” et“E2”.

Ensuite, nous créons une requête qui ajoutera les données après le tableau contenant la cellule «A1».

L'optionINSERT_ROWS signifie que nous voulons que les données soient ajoutées à une nouvelle ligne et ne remplacent aucune donnée existante après la table. Cela signifie que l'exemple écrira la plage «A7:B7» lors de sa première exécution.

Lors des exécutions suivantes, la table qui commence à la cellule“A1” s'étendra désormais pour inclure la ligne“A7:B7”, donc une nouvelle ligne va à la ligne“A8:B8”, et ainsi de suite.

Nous devons également définir la propriétéincludeValuesInResponse sur true si nous voulons vérifier la réponse à une requête. Par conséquent, l'objet de réponse contiendra les données mises à jour.

6. Lire des valeurs à partir d'une feuille

Vérifions que nos valeurs ont été écrites correctement en les lisant sur la feuille.

Nous pouvons le faire en utilisant la méthodespreadsheets().values().get() pour lire une seule plage ou la méthodebatchUpdate() pour lire plusieurs plages:

List ranges = Arrays.asList("E1","E4");
BatchGetValuesResponse readResult = sheetsService.spreadsheets().values()
  .batchGet(SPREADSHEET_ID)
  .setRanges(ranges)
  .execute();

ValueRange januaryTotal = readResult.getValueRanges().get(0);
assertThat(januaryTotal.getValues().get(0).get(0))
  .isEqualTo("40");

ValueRange febTotal = readResult.getValueRanges().get(1);
assertThat(febTotal.getValues().get(0).get(0))
  .isEqualTo("25");

Ici, nous lisons les plages“E1” et“E4” et vérifions qu'elles contiennent le total pour chaque mois que nous avons écrit auparavant.

7. Créer de nouvelles feuilles de calcul

Outre la lecture et la mise à jour des valeurs, nous pouvons également manipuler des feuilles ou des feuilles de calcul entières en utilisant les collectionsspreadsheets() etspreadsheets().sheets().

Voyons un exemple de création d'une nouvelle feuille de calcul:

@Test
public void test() throws IOException {
    Spreadsheet spreadSheet = new Spreadsheet().setProperties(
      new SpreadsheetProperties().setTitle("My Spreadsheet"));
    Spreadsheet result = sheetsService
      .spreadsheets()
      .create(spreadSheet).execute();

    assertThat(result.getSpreadsheetId()).isNotNull();
}

Ici, nous créons d'abord un objetSpreadsheet avec le titre «MySpreadsheet”, puis nous construisons et envoyons une requête en utilisant les méthodescreate() etexecute().

La nouvelle feuille de calcul sera privée et placée dans le Drive de l'utilisateur connecté.

8. Autres opérations de mise à jour

La plupart des autres opérations prennent la forme d'un objetRequest, que nous ajoutons ensuite à une liste et que nous utilisons pour construire unBatchUpdateSpreadsheetRequest.

Voyons comment nous pouvons envoyer deux demandes pour modifier le titre d'une feuille de calcul et copier-coller un ensemble de cellules d'une feuille à une autre:

@Test
public void whenUpdateSpreadSheetTitle_thenOk() throws IOException {
    UpdateSpreadsheetPropertiesRequest updateSpreadSheetRequest
      = new UpdateSpreadsheetPropertiesRequest().setFields("*")
      .setProperties(new SpreadsheetProperties().setTitle("Expenses"));

    CopyPasteRequest copyRequest = new CopyPasteRequest()
      .setSource(new GridRange().setSheetId(0)
        .setStartColumnIndex(0).setEndColumnIndex(2)
        .setStartRowIndex(0).setEndRowIndex(1))
      .setDestination(new GridRange().setSheetId(1)
        .setStartColumnIndex(0).setEndColumnIndex(2)
        .setStartRowIndex(0).setEndRowIndex(1))
      .setPasteType("PASTE_VALUES");

    List requests = new ArrayList<>();
    requests.add(new Request()
      .setCopyPaste(copyRequest));
    requests.add(new Request()
      .setUpdateSpreadsheetProperties(updateSpreadSheetRequest));

    BatchUpdateSpreadsheetRequest body
      = new BatchUpdateSpreadsheetRequest().setRequests(requests);

    sheetsService.spreadsheets().batchUpdate(SPREADSHEET_ID, body).execute();
}

Ici, nous créons un objetUpdateSpreadSheetPropertiesRequest qui spécifie le nouveau titre, un objetCopyPasteRequest qui contient la source et la destination de l'opération puis ajoutons ces objets à unList deRequests.

Ensuite, nous exécutons les deux requêtes sous forme de mise à jour par lots.

De nombreux autres types de demandes sont disponibles pour une utilisation similaire. Par exemple, nous pouvons créer une nouvelle feuille dans une feuille de calcul avec unAddSheetRequest ou modifier les valeurs avec unFindReplaceRequest.

Nous pouvons effectuer d'autres opérations telles que modifier les bordures, ajouter des filtres ou fusionner des cellules. La liste complète des typesRequest est disponiblehere.

9. Conclusion

Dans cet article, nous avons vu comment nous pouvons nous connecter à l'API Google Sheets à partir d'une application Java et quelques exemples de manipulation de documents stockés dans Google Sheets.

Le code source complet des exemples peut être trouvéover on GitHub.