Доступ к стандартным функциям электронных таблиц с помощью Sheets API на C#

В настоящее время я работаю над небольшим приложением с C # и .NET, где я пытаюсь имитировать электронную таблицу с графическим интерфейсом, одновременно обновляя электронную таблицу на Google Диске.

Мне нужно будет использовать некоторые функции, и я пытался найти в документации, можно ли получить доступ к собственным функциям через API, но безуспешно. Я также пытался сделать простой хак, вставив функцию в виде строки непосредственно в ячейку, вот так (извините за использование списка, я просто скопировал его из другой функции, где пытался заполнить несколько ячеек одновременно ),

var valuesToAppend = new List<object>() { "=MAX(A1:A5)" };

но затем я также передал кавычки, которые сделали его бесполезным.

Может быть, это потому, что сегодня суббота, и моя голова не работала должным образом, но я не нашел решения этой проблемы. Есть ли кто-нибудь, кто знает, могу ли я легко получить доступ к методам или мне нужно пройти долгий путь и реализовать функции и выполнить вычисления локально?

Изменить: Чтобы уточнить, я надеялся вставить формулы, такие как = MAX (диапазон), = SUM (диапазон) в ячейку с моего сервера через API листов.


person Terris    schedule 07.04.2018    source источник
comment
Что именно вы подразумеваете под доступом к родным функциям? Вы пытаетесь установить значение ячейки в формулу (что, я считаю, возможно возможно) или вычислить значение формулы и получить это значение в коде C#?   -  person Jon Skeet    schedule 09.04.2018
comment
Извините за поздний ответ, увлекся другими вещами. Это было первое, что я искал, и я совершенно забыл, что они называются формулами (теперь я действительно чувствую себя тупым). Я хочу обоих на самом деле. Я хочу установить значение ячейки в значение формулы (чтобы электронная таблица обновлялась), а затем получить вычисленное значение впоследствии.   -  person Terris    schedule 15.04.2018
comment
Я считаю, что это абсолютно возможно. Сам я еще не использовал Sheets API, но буду рад немного изучить его. Итак, просто чтобы проверить, правильно ли я вас понимаю, если я выполню следующие действия: а) вручную создам электронную таблицу с некоторыми значениями; б) передать идентификатор этой электронной таблицы какому-либо коду; c) (в коде) установить значение ячейки в электронной таблице в формулу; d) (в коде) получить видимое (вычисляемое) значение этой ячейки и (скажем) распечатать его в консоли... это будет охватывать все, что вы пытаетесь сделать?   -  person Jon Skeet    schedule 15.04.2018
comment
Это было бы более или менее именно то, что я ищу. Я начал рассматривать пакетное обновление для добавления правил формулы в набор ячеек, но моя первоначальная мысль заключалась в том, что это выглядит несколько неэффективным способом сделать это, когда единственное, что мне нужно, это одна ячейка.   -  person Terris    schedule 15.04.2018
comment
Отлично - было бы хорошо обновить ваш вопрос, чтобы сделать его более понятным для будущих читателей, но я добавил ответ, который, как я проверил, делает то, что вы хотите. Он выполняет обновление и выборку в одном запросе, но я предполагаю, что вы сможете решить, как получить вычисленное значение отдельно, если вам это нужно.   -  person Jon Skeet    schedule 15.04.2018
comment
Благодарю вас! Да, этого должно быть более чем достаточно для меня, чтобы работать. Кажется, что программирование после пьяной ночи — не лучший способ научиться чему-то новому. Я смотрел на то, что вы сделали, но по какой-то причине я не мог связать это вместе.   -  person Terris    schedule 15.04.2018


Ответы (1)


Да, вы абсолютно точно можете это сделать. Вам нужно указать ValueInputOption как USERENTERED для запроса на обновление, и вы можете запросить вернуть содержимое ячейки (как вычисленное значение) в ответ.

Итак, что-то вроде:

var valueRange = new ValueRange { Values = new[] { new object[] { formula } } };
var request = service.Spreadsheets.Values.Update(valueRange, spreadsheetId, cell);
request.ValueInputOption = ValueInputOptionEnum.USERENTERED;
request.IncludeValuesInResponse = true;
request.ResponseValueRenderOption = ResponseValueRenderOptionEnum.UNFORMATTEDVALUE;
var response = request.Execute();
Console.WriteLine($"Result: {response.UpdatedData.Values[0][0]}");

Вот полный пример, содержащий этот код:

using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using Google.Apis.Sheets.v4;
using Google.Apis.Sheets.v4.Data;
using System;
using System.IO;
using System.Threading;
using static Google.Apis.Sheets.v4.SpreadsheetsResource.ValuesResource.UpdateRequest;

class Program
{
    static void Main(string[] args)
    {
        // Set-up part...
        if (args.Length != 4)
        {
            Console.WriteLine("Required values: <client secrets file> <spreadsheet-ID> <cell> <formula>");
            Console.WriteLine("Example: <secrets.json> <sheet ID> E1 =MAX(A1:D1)");
            return;
        }
        var secretsFile = args[0];
        var spreadsheetId = args[1];
        var cell = args[2];
        var formula = args[3];

        var secrets = File.ReadAllBytes(secretsFile);

        // Don't usually use Task<T>.Result, but this is just a demo console app...
        // we shouldn't have any deadlock worries.
        var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
            new MemoryStream(secrets),
            new[] { SheetsService.Scope.Spreadsheets },
            "user", // Key in file store
            CancellationToken.None).Result;

        var service = new SheetsService(new BaseClientService.Initializer
        {
            HttpClientInitializer = credential,
            ApplicationName = "Google Sheets API demo"
        });

        // Interesting bit :)
        var valueRange = new ValueRange { Values = new[] { new object[] { formula } } };
        var request = service.Spreadsheets.Values.Update(valueRange, spreadsheetId, cell);
        // Pretend we're a user typing in this value...
        request.ValueInputOption = ValueInputOptionEnum.USERENTERED;
        // Get the computed value back in the response
        request.IncludeValuesInResponse = true;
        // Retrieve the value unformatted (so as a number in the JSON)
        // rather than either the uncomputed value, or the formatted value as a string
        request.ResponseValueRenderOption = ResponseValueRenderOptionEnum.UNFORMATTEDVALUE;
        var response = request.Execute();
        Console.WriteLine($"Result: {response.UpdatedData.Values[0][0]}");
    }
}
person Jon Skeet    schedule 15.04.2018
comment
Меня действительно раздражает, насколько это было просто, я только пропустил ValueInputOption. Еще раз спасибо! - person Terris; 15.04.2018