За последние 24 часа нас посетили 18280 программистов и 1581 робот. Сейчас ищут 1144 программиста ...

Google Sheets API - batchUpdate

Тема в разделе "PHP для новичков", создана пользователем alibek23, 10 янв 2024.

  1. alibek23

    alibek23 Новичок

    С нами с:
    19 июл 2023
    Сообщения:
    7
    Симпатии:
    0
    Есть скрипт, работающий с онлайн-таблицами Google.
    Для скрипта есть самописная библиотека-оболочка, использующая стандартную библиотеку.

    Фрагмент оболочки:
    PHP:
    1.     /***
    2.      * Получить данные с листа
    3.      */
    4.     public function getValues($sheet, $range=null, $options=null, $delay=1)
    5.     {
    6.         $svc = $this->store['service'];
    7.         $id = $this->store['document'];
    8.         if (isset($options)) {
    9.             if (!is_array($options)) $options = ['valueRenderOption'=>$options];
    10.             $options['dateTimeRenderOption'] = 'FORMATTED_STRING';
    11.         } else {
    12.             $options = [];
    13.         }
    14.         if (is_array($range)) {
    15.             $params = ['ranges'=>[]];
    16.             foreach ($range as $r) $params['ranges'][] = $sheet . '!'.$r;
    17.             $res = $svc->spreadsheets_values->batchGet($id, $params, $options);
    18.         } else {
    19.             $res = $svc->spreadsheets_values->get($id, $sheet . (isset($range) ? '!'.$range : ''), $options);
    20.         }
    21.         if ($delay) sleep($delay);
    22.         return $res;
    23.     }
    24.  
    25.     /***
    26.      * Изменить данные на листе
    27.      */
    28.     public function setValues($sheet, $range, $data, $delay=1)
    29.     {
    30.         $svc = $this->store['service'];
    31.         $id = $this->store['document'];
    32.         if (is_array($range)) {
    33.             foreach ($range as &$r) $r = $sheet . '!'.$r;
    34.             unset($r);
    35.             $data = new \Google_Service_Sheets_ValueRange(['range'=>$range, 'values'=>$data]);
    36.             $req = new \Google_Service_Sheets_BatchUpdateValuesRequest(['valueInputOption'=>'USER_ENTERED', 'data'=>$data]);
    37.             $res = $svc->spreadsheets_values->batchUpdate($id, $req);
    38.         } else {
    39.             $options = ['valueInputOption'=>'USER_ENTERED'];
    40.             $data = new \Google_Service_Sheets_ValueRange(['values'=>$data]);
    41.             $res = $svc->spreadsheets_values->update($id, $sheet . (isset($range) ? '!'.$range : ''), $data, $options);
    42.         }
    43.         if ($delay) sleep($delay);
    44.         return $res;
    45.     }
    В методы getValues и setValues передается имя листа и диапазон.
    Если диапазон является массивом, то используются batch-методы, иначе используются обычные методы get/update.

    Считывание данных работает нормально:
    PHP:
    1. $r = ['F2', 'G2', 'H2:I3'];
    2. print "*RANGE: "; print_r($r);
    3. $res = $net->getValues('Коммутаторы доступа', $r);
    4. print "*GET: "; print_r($res);
    Вывод:
    Код (Text):
    1. *RANGE: Array
    2. (
    3.     [0] => F2
    4.     [1] => G2
    5.     [2] => H2:I3
    6. )
    7. *GET: Google_Service_Sheets_BatchGetValuesResponse Object
    8. (
    9.     [collection_key:protected] => valueRanges
    10.     [spreadsheetId] => ...
    11.     [valueRangesType:protected] => Google_Service_Sheets_ValueRange
    12.     [valueRangesDataType:protected] => array
    13.     [internal_gapi_mappings:protected] => Array
    14.         (
    15.         )
    16.  
    17.     [modelData:protected] => Array
    18.         (
    19.         )
    20.  
    21.     [processed:protected] => Array
    22.         (
    23.         )
    24.  
    25.     [valueRanges] => Array
    26.         (
    27.             [0] => Google_Service_Sheets_ValueRange Object
    28.                 (
    29.                     [collection_key:protected] => values
    30.                     [majorDimension] => ROWS
    31.                     [range] => 'Лист1'!F2
    32.                     [values] => Array
    33.                         (
    34.                             [0] => Array
    35.                                 (
    36.                                     [0] => abc
    37.                                 )
    38.  
    39.                         )
    40.  
    41.                     [internal_gapi_mappings:protected] => Array
    42.                         (
    43.                         )
    44.  
    45.                     [modelData:protected] => Array
    46.                         (
    47.                         )
    48.  
    49.                     [processed:protected] => Array
    50.                         (
    51.                         )
    52.  
    53.                 )
    54.  
    55.             [1] => Google_Service_Sheets_ValueRange Object
    56.                 (
    57.                     [collection_key:protected] => values
    58.                     [majorDimension] => ROWS
    59.                     [range] => 'Лист1'!G2
    60.                     [values] =>
    61.                     [internal_gapi_mappings:protected] => Array
    62.                         (
    63.                         )
    64.  
    65.                     [modelData:protected] => Array
    66.                         (
    67.                         )
    68.  
    69.                     [processed:protected] => Array
    70.                         (
    71.                         )
    72.  
    73.                 )
    74.  
    75.             [2] => Google_Service_Sheets_ValueRange Object
    76.                 (
    77.                     [collection_key:protected] => values
    78.                     [majorDimension] => ROWS
    79.                     [range] => 'Лист1'!H2:I3
    80.                     [values] =>
    81.                     [internal_gapi_mappings:protected] => Array
    82.                         (
    83.                         )
    84.  
    85.                     [modelData:protected] => Array
    86.                         (
    87.                         )
    88.  
    89.                     [processed:protected] => Array
    90.                         (
    91.                         )
    92.  
    93.                 )
    94.  
    95.         )
    96.  
    97. )
    Если я полученный результат использую в setValues, то метод отрабатывает без ошибок, но ничего не меняется:
    PHP:
    1. $tmp = $res;
    2. $tmp->valueRanges[0]->values[0][0] = 'xyz';
    3. print "*ARR: "; print_r($tmp);
    4. $ret = $net->setValues('Лист1', $r, $tmp);
    5. print "*SET: "; print_r($ret);
    Вывод:
    Код (Text):
    1. *ARR: Google_Service_Sheets_BatchGetValuesResponse Object
    2. (
    3.     [collection_key:protected] => valueRanges
    4.     [spreadsheetId] => ...
    5.     [valueRangesType:protected] => Google_Service_Sheets_ValueRange
    6.     [valueRangesDataType:protected] => array
    7.     [internal_gapi_mappings:protected] => Array
    8.         (
    9.         )
    10.  
    11.     [modelData:protected] => Array
    12.         (
    13.         )
    14.  
    15.     [processed:protected] => Array
    16.         (
    17.         )
    18.  
    19.     [valueRanges] => Array
    20.         (
    21.             [0] => Google_Service_Sheets_ValueRange Object
    22.                 (
    23.                     [collection_key:protected] => values
    24.                     [majorDimension] => ROWS
    25.                     [range] => 'Лист1'!F2
    26.                     [values] => Array
    27.                         (
    28.                             [0] => Array
    29.                                 (
    30.                                     [0] => xyz
    31.                                 )
    32.  
    33.                         )
    34.  
    35.                     [internal_gapi_mappings:protected] => Array
    36.                         (
    37.                         )
    38.  
    39.                     [modelData:protected] => Array
    40.                         (
    41.                         )
    42.  
    43.                     [processed:protected] => Array
    44.                         (
    45.                         )
    46.  
    47.                 )
    48.  
    49.             [1] => Google_Service_Sheets_ValueRange Object
    50.                 (
    51.                     [collection_key:protected] => values
    52.                     [majorDimension] => ROWS
    53.                     [range] => 'Лист1'!G2
    54.                     [values] =>
    55.                     [internal_gapi_mappings:protected] => Array
    56.                         (
    57.                         )
    58.  
    59.                     [modelData:protected] => Array
    60.                         (
    61.                         )
    62.  
    63.                     [processed:protected] => Array
    64.                         (
    65.                         )
    66.  
    67.                 )
    68.  
    69.             [2] => Google_Service_Sheets_ValueRange Object
    70.                 (
    71.                     [collection_key:protected] => values
    72.                     [majorDimension] => ROWS
    73.                     [range] => 'Лист1'!H2:I3
    74.                     [values] =>
    75.                     [internal_gapi_mappings:protected] => Array
    76.                         (
    77.                         )
    78.  
    79.                     [modelData:protected] => Array
    80.                         (
    81.                         )
    82.  
    83.                     [processed:protected] => Array
    84.                         (
    85.                         )
    86.  
    87.                 )
    88.  
    89.         )
    90.  
    91. )
    92. *SET: Google_Service_Sheets_BatchUpdateValuesResponse Object
    93. (
    94.     [collection_key:protected] => responses
    95.     [responsesType:protected] => Google_Service_Sheets_UpdateValuesResponse
    96.     [responsesDataType:protected] => array
    97.     [spreadsheetId] => ...
    98.     [totalUpdatedCells] =>
    99.     [totalUpdatedColumns] =>
    100.     [totalUpdatedRows] =>
    101.     [totalUpdatedSheets] =>
    102.     [internal_gapi_mappings:protected] => Array
    103.         (
    104.         )
    105.  
    106.     [modelData:protected] => Array
    107.         (
    108.         )
    109.  
    110.     [processed:protected] => Array
    111.         (
    112.         )
    113.  
    114. )
    Метод выполняется без ошибок, но в ячейке F2 содержимое не изменяется.

    Если же я пробую сделать так:
    PHP:
    1. $tmp = []; foreach ($res->valueRanges as $v) $tmp[] = $v->values;
    2. $tmp[0][0][0] = 'xyz';
    3. print "*ARR: "; print_r($tmp);
    4. $ret = $net->setValues('Коммутаторы доступа', $r, $tmp);
    5. print "*SET: "; print_r($ret);
    то получаю ошибку:
    Код (Text):
    1. *ARR: Array
    2. (
    3.     [0] => Array
    4.         (
    5.             [0] => Array
    6.                 (
    7.                     [0] => xyz
    8.                 )
    9.  
    10.         )
    11.  
    12.     [1] =>
    13.     [2] =>
    14. )
    15. PHP Fatal error:  Uncaught Google\Service\Exception: {
    16.   "error": {
    17.     "code": 400,
    18.     "message": "Invalid JSON payload received. Unknown name \"0\" at 'data[0]': Cannot find field.",
    19.     "errors": [
    20.       {
    21.         "message": "Invalid JSON payload received. Unknown name \"0\" at 'data[0]': Cannot find field.",
    22.         "reason": "invalid"
    23.       }
    24.     ],
    25.     "status": "INVALID_ARGUMENT",
    26.     "details": [
    27.       {
    28.         "@type": "type.googleapis.com/google.rpc.BadRequest",
    29.         "fieldViolations": [
    30.           {
    31.             "field": "data[0]",
    32.             "description": "Invalid JSON payload received. Unknown name \"0\" at 'data[0]': Cannot find field."
    33.           }
    34.         ]
    35.       }
    36.     ]
    37.   }
    38. }
    В примере в метод передается пустой массив, так и меня тоже работает.
    А как обновить ячейки данными?
     
  2. don.bidon

    don.bidon Активный пользователь

    С нами с:
    28 мар 2021
    Сообщения:
    914
    Симпатии:
    143
    Предлагаю перенести во фриланс...
     
  3. alibek23

    alibek23 Новичок

    С нами с:
    19 июл 2023
    Сообщения:
    7
    Симпатии:
    0
    Мне достаточно будет примера заполнения поля values.
     
  4. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.788
    Симпатии:
    1.328
    Адрес:
    Лень
    Занимался Google таблицами до 2022 года.
    Если будет что-то полезное из перечисленного моего кода, который уже летит на свалку по неактуальности.

    composer - "google/apiclient": "2.12.1",
    PHP:
    1. <?php
    2.  
    3. declare ( strict_types = 1 );
    4.  
    5. function getGoogleClient(): Google_Client
    6. {
    7.     static $client;
    8.    
    9.     if ( is_null ( $client ) )
    10.     {
    11.         $client = new Google_Client;
    12.        
    13.         $client -> useApplicationDefaultCredentials();
    14.        
    15.         $client -> setScopes( [
    16.             \Google_Service_Sheets :: SPREADSHEETS,
    17.             \Google_Service_Drive :: DRIVE,
    18.         ] );
    19.     }
    20.    
    21.     return $client;
    22. }
    23.  
    24. function getGoogleServiceDrive(): Google_Service_Drive
    25. {
    26.     static $service;
    27.    
    28.     if ( is_null ( $service ) )
    29.     {
    30.         $service = new Google_Service_Drive( getGoogleClient() );
    31.     }
    32.    
    33.     return $service;
    34. }
    35.  
    36. function GoogleRemovePermission( string $fileId, string $permissionId ): void
    37. {
    38.     getGoogleServiceDrive() -> permissions -> delete( $fileId, $permissionId );
    39. }
    40.  
    41. function GoogleAddPermission( string $fileId, string $email, string $role = 'reader' ): string
    42. {
    43.     $publicPermission = new Google_Service_Drive_Permission();
    44.    
    45.     $publicPermission -> setEmailAddress( $email );
    46.    
    47.     $publicPermission -> setType( 'user' );
    48.    
    49.     $publicPermission -> setRole( $role );
    50.    
    51.     return getGoogleServiceDrive() -> permissions -> create( $fileId, $publicPermission, [ 'sendNotificationEmail' => false ] ) -> getId();
    52. }
    53.  
    54. function GoogleTableAddRow( string $spreadsheetId, string $page, array $newlines, callable $call_error ): void
    55. {
    56.     try
    57.     {
    58.         $values = ( $service = new Google_Service_Sheets( getGoogleClient() ) )
    59.             -> spreadsheets_values
    60.             -> get( $spreadsheetId, $page )
    61.             -> getValues();
    62.        
    63.         $service -> spreadsheets_values -> update(
    64.             $spreadsheetId,
    65.             $page . '!A' . ( count ( $values ) + 1 ),
    66.             new Google_Service_Sheets_ValueRange( [ 'values' => $newlines ] ),
    67.             [ 'valueInputOption' => 'RAW' ]
    68.         );
    69.     }
    70.     catch ( \Google\Service\Exception $e )
    71.     {
    72.         $call_error( $e );
    73.     }
    74. }
    --- Добавлено ---
    PHP:
    1. //Для доступа к приватной гугл таблицы
    2. putenv ( 'GOOGLE_APPLICATION_CREDENTIALS=' . __DIR__ . '/mousezver******.json' );
     
  5. alibek23

    alibek23 Новичок

    С нами с:
    19 июл 2023
    Сообщения:
    7
    Симпатии:
    0
    Спасибо. Правда перечисленное у меня и так работает без проблем.
    Но сравню со своим кодом, возможно что-то улучшу.
     
  6. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.788
    Симпатии:
    1.328
    Адрес:
    Лень
    так же есть код в GoogleTableAddRow
     
  7. alibek23

    alibek23 Новичок

    С нами с:
    19 июл 2023
    Сообщения:
    7
    Симпатии:
    0
    Обычный update у меня работает без проблем.
    У меня проблемы с batchUpdate.