Гость
Map
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Вопрос к знатокам Google Sheets / 3 сообщений из 3, страница 1 из 1
26.11.2021, 12:44
    #40115215
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос к знатокам Google Sheets
Подскажите, как правильно работать с Sheets API ?

У меня есть скрипт, который ежедневно запускается, рассчитывает определенные значения и записывает результат в Google-таблицу (точнее должен записывать).
В Google-таблице 50 столбцов, в первом указана дата, в остальных значения для этой даты.
Скрипт подключается к таблице, находит в таблице строку с нужной датой (если не находит, то добавляет новую строку), а также вносит в таблицу соответствующие значения.

Проблема в следующем.
В переменной $row находится номер строки, в которой нужно сохранять значения.
Текущие значения этой строки я считываю так:
Код: php
1.
$rs = $sh->getValues("{$ss}!{$row}:{$row}");


Здесь $sh это ссылка на объект GoogleSheets, $ss это наименование листа. В $rs возвращается ссылка на результат (объект), в этом ссылке один из методов ($rs->values) возвращает массив массивов (массив строк, внутри которого массив ячеек).

Проблема с пустыми значениями.
A) Если в строке отсутствуют данные, то в $rs->values будет пустое значение (null).
B) Если в строке заполнены все ячейки, то в $rs->values[0] возвратится массив из 50 элементов.
C) Если в строке заполнены только первые три ячейки, то в $rs->values[0] возвратится массив из 3 элементов, остальные 47 будут отсутствовать.
D) Если в строке заполнены только первая и последняя ячейки, то в $rs->values[0] возвратится массив из 50 элементов, в все значения (кроме крайних) будут пустыми.

Но проблема с тем, чтобы записать данные в таблицу.
Если я считываю массив, изменяю его значения и записываю его обратно, то все работает:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
	if (empty($rs->values)) {
		$rs = [];
	} else {
		$rs = (array)$rs->values[0];
	}
	foreach ($data as $fld=>$val)
	{
		$col = $map[$fld];
		if (count($rs) < $col) $rs = array_merge($rs, array_fill(0, ($col - count($rs)), null));
		$rs[$col-1] = $val;
	}
	$sh->setValues($ss, "{$row}:{$row}", [$rs]);


Такой код успешно работает для вариантов B и D.
Но если я добавляю ячейки справа (например были заполнены только первые два столбца, а мне нужно добавить значение в 20 столбец), то возникает ошибка:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
Uncaught Google\Service\Exception: {
  "error": {
    "code": 400,
    "message": "Invalid JSON payload received. Unknown name \"0\" at 'data.values[0]': Cannot find field.\nInvalid JSON payload received. Unknown name \"49\" at 'data.values[0]': Cannot find field.",
    "errors": [
      {
        "message": "Invalid JSON payload received. Unknown name \"0\" at 'data.values[0]': Cannot find field.\nInvalid JSON payload received. Unknown name \"49\" at 'data.values[0]': Cannot find field.",
        "reason": "invalid"
      }
    ],
    "status": "INVALID_ARGUMENT"
  }
}

Значения данных в скрипте (print_r(['data'=>$data, 'rs'=>$rs])):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
Array
(
    [data] => Array
        (
            [date] => 2021-01-01
            [notes] => test
        )

    [rs] => Array
        (
            [0] => 2021-01-01
            [1] => 
            [2] => 
            [3] => 
            [4] => 
            [5] => 
            [6] => 
            [7] => 
            [8] => 
            [9] => 
            [10] => 
            [11] => 
            [12] => 
            [13] => 
            [14] => 
            [15] => 
            [16] => 
            [17] => 
            [18] => 
            [19] => 
            [20] => 
            [21] => 
            [22] => 
            [23] => 
            [24] => 
            [25] => 
            [26] => 
            [27] => 
            [28] => 
            [29] => 
            [30] => 
            [31] => 
            [32] => 
            [33] => 
            [34] => 
            [35] => 
            [36] => 
            [37] => 
            [38] => 
            [39] => 
            [40] => 
            [41] => 
            [42] => 
            [43] => 
            [44] => 
            [45] => 
            [46] => 
            [47] => 
            [48] => 
            [49] => test
        )

)

Не могу понять, что не устраивает Google.
...
Рейтинг: 0 / 0
26.11.2021, 12:46
    #40115217
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос к знатокам Google Sheets
Обертка (GoogleSheets) предельно простая:
Код: php
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
	/**
	 * $id
	 *   Идентификатор документа (SpreadsheetID).
	 * $token
	 *   Токен авторизации (json-файл).
	 * $options
	 *   Ассоциированный массив с параметрами:
	 */
	public function __construct($id, $token, $options=null)
	{
		global $_BASE;
		if (!isset($id, $token)) throw new \InvalidArgumentException('Required parameter ommited');
		if (is_array($token)) throw new \InvalidArgumentException('Inline token not implemented, use json-file');
		if (substr($token, -5) != '.json') $token .= '.json';
		if (strpos($token, '/') === false) $token = "{$_BASE}/cfg/" . $token;
		$client = new \Google_Client();
		if (!$client) throw new \RuntimeException("Google_Client instancing failed!");
		$client->setScopes([\Google_Service_Sheets::DRIVE, \Google_Service_Sheets::SPREADSHEETS]);
		putenv("GOOGLE_APPLICATION_CREDENTIALS={$token}");
		$client->useApplicationDefaultCredentials();
		$service = new \Google_Service_Sheets($client);
		if (!$service) throw new \RuntimeException("Google_Service_Sheets instancing failed!");
		$sheet = $service->spreadsheets->get($id);
		if (!$sheet) throw new \RuntimeException("Google_Service_Sheets_Spreadsheet instancing failed!");
		$this->store = [];
		$this->store['client'] = $client;
		$this->store['service'] = $service;
		$this->store['document'] = $id;
		$this->store['sheet'] = $sheet;
	}
...
	/***
	 * Получить данные с листа
	 */
	public function getValues($sheet, $range=null, $options=[])
	{
		$svc = $this->store['service'];
		$id = $this->store['document'];
		if (isset($options))
		{
			if (!is_array($options)) $options = ['valueRenderOption'=>$options];
			$options['dateTimeRenderOption'] = 'FORMATTED_STRING';
		}
		$res = $svc->spreadsheets_values->get($id, $sheet . (isset($range) ? '!'.$range : ''), $options);
		sleep(1);
		return $res;
	}

	/***
	 * Изменить данные на листе
	 */
	public function setValues($sheet, $range, $data)
	{
		$svc = $this->store['service'];
		$id = $this->store['document'];
		$data = new \Google_Service_Sheets_ValueRange(['values'=>$data]);
		$options = ['valueInputOption'=>'USER_ENTERED'];
		$res = $svc->spreadsheets_values->update($id, $sheet . (isset($range) ? '!'.$range : ''), $data, $options);
		sleep(1);
		return $res;
	}
...
Рейтинг: 0 / 0
26.11.2021, 12:51
    #40115218
Alibek B
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Вопрос к знатокам Google Sheets
Хм...

Сделал так: if (count($rs) < $col) $rs = array_merge($rs, array_fill(0, ($col - count($rs)), ''));
Теперь ошибок нет.
То есть API чем-то не нравится null.
...
Рейтинг: 0 / 0
Форумы / PHP, Perl, Python [игнор отключен] [закрыт для гостей] / Вопрос к знатокам Google Sheets / 3 сообщений из 3, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали тему (0):
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]