Основные концепции программирования с помощью API JavaScript для ExcelFundamental programming concepts with the Excel JavaScript API

В этой статье описано, как создавать надстройки для Excel 2016 или более поздней версии с помощью API JavaScript для Excel.This article describes how to use the Excel JavaScript API to build add-ins for Excel 2016 or later. В статье изложены основные принципы, которые являются фундаментальными при использовании этого API, а также имеются рекомендации по выполнению определенных задач, например чтению данных из большого диапазона или записи данных в него, изменения всех ячеек в диапазоне и много другого.It introduces core concepts that are fundamental to using the API and provides guidance for performing specific tasks such as reading or writing to a large range, updating all cells in range, and more.

Асинхронный характер API ExcelAsynchronous nature of Excel APIs

Веб-надстройки Excel работают в контейнере браузера, внедренном в приложение Office на платформах для настольных ПК, например Office для Windows, и работающем в iFrame HTML в Office в Интернете. API Office.js не может синхронно взаимодействовать с ведущим приложением Excel на всех поддерживаемых платформах из соображений производительности. Таким образом, при вызове API sync() в Office.js возвращается обещание, которое разрешается, когда приложение Excel выполняет запрошенные действия чтения или записи. Кроме того, вы можете поместить в очередь несколько действий, например для настройки свойств или вызова методов, а затем запустить их в виде пакета команд в одном вызове метода sync(), а не отправлять отдельные запросы для каждого действия. В следующих разделах описано, как сделать это, используя API Excel.run() и sync().The web-based Excel add-ins run inside a browser container that is embedded within the Office application on desktop-based platforms such as Office on Windows and runs inside an HTML iFrame in Office Online. Enabling the Office.js API to interact synchronously with the Excel host across all supported platforms is not feasible due to performance considerations. Therefore, the sync() API call in Office.js returns a promise that is resolved when the Excel application completes the requested read or write actions. Also, you can queue up multiple actions, such as setting properties or invoking methods, and run them as a batch of commands with a single call to sync(), rather than sending a separate request for each action. The following sections describe how to accomplish this using the Excel.run() and sync() APIs.

Excel.runExcel.run

Excel.run выполняет функцию, в которой вы указываете действия, которые необходимо совершить над объектной моделью Excel. Excel.run автоматически создает контекст запроса, который вы можете использовать для взаимодействия с объектами Excel. Когда Excel.run завершает работу, обещание разрешается, и все объекты, которые были выделены в среде выполнения, будут автоматически разблокированы.Excel.run executes a function where you specify the actions to perform against the Excel object model. Excel.run automatically creates a request context that you can use to interact with Excel objects. When Excel.run completes, a promise is resolved, and any objects that were allocated at runtime are automatically released.

В примере ниже показано, как использовать Excel.run. Оператор catch перехватывает и записывает ошибки, возникающие в Excel.run, в журнал.The following example shows how to use Excel.run. The catch statement catches and logs errors that occur within the Excel.run.

Excel.run(function (context) {
    // You can use the Excel JavaScript API here in the batch function
    // to execute actions on the Excel object model.
    console.log('Your code goes here.');
}).catch(function (error) {
    console.log('error: ' + error);
    if (error instanceof OfficeExtension.Error) {
        console.log('Debug info: ' + JSON.stringify(error.debugInfo));
    }
});

Параметры выполненияRun options

В Excel.run есть перегрузка, получающая объект RunOptions.Excel.run has an overload that takes in a RunOptions object. Он содержит набор свойств, влияющих на поведение платформы при выполнении функции.This contains a set of properties that affect platform behavior when the function runs. Ниже перечислены поддерживаемые в настоящее время свойства.The following property is currently supported:

  • delayForCellEdit: определяет, откладывает ли Excel пакетный запрос до выхода пользователя из режима правки ячейки.delayForCellEdit: Determines whether Excel delays the batch request until the user exits cell edit mode. Если присвоено значение true, пакетный запрос откладывается и запускается, когда пользователь выходит из режима правки ячейки.When true, the batch request is delayed and runs when the user exits cell edit mode. Если присвоено значение false, происходит автоматический сбой пакетного запроса, если пользователь находится в режиме правки ячейки (приводит к ошибке обращения к пользователю).When false, the batch request automatically fails if the user is in cell edit mode (causing an error to reach the user). Поведение по умолчанию при отсутствии заданного свойства delayForCellEdit аналогично поведению при значении false.The default behavior with no delayForCellEdit property specified is equivalent to when it is false.
Excel.run({ delayForCellEdit: true }, function (context) { ... })

Контекст запросаRequest context

Excel и ваша надстройка запускаются как два отдельных процесса. Так как они используют разные среды выполнения, надстройкам Excel требуется объект RequestContext, чтобы можно было подключать надстройку к объектам в Excel, например к листам, диапазонам, диаграммам и таблицам.Excel and your add-in run in two different processes. Since they use different runtime environments, Excel add-ins require a RequestContext object in order to connect your add-in to objects in Excel such as worksheets, ranges, charts, and tables.

Прокси-объектыProxy objects

Объекты JavaScript в Excel, которые вы объявляете и используете в надстройке, представляют собой прокси-объекты. Все методы, которые вы вызываете, либо свойства, которые вы настраиваете либо загружаете, в прокси-объектах просто добавляются в очередь команд, ожидающих выполнения. Когда вы вызываете метод sync() в контексте запроса (например, context.sync()), команды, помещенные в очередь, передаются в Excel и выполняются. По существу, API JavaScript для Excel ориентирован на работу с пакетами. Вы можете поместить в очередь любое количество изменений в контексте запроса, а затем вызвать метод sync(), чтобы запустить пакет команд, помещенных в очередь.The Excel JavaScript objects that you declare and use in an add-in are proxy objects. Any methods that you invoke or properties that you set or load on proxy objects are simply added to a queue of pending commands. When you call the sync() method on the request context (for example, context.sync()), the queued commands are dispatched to Excel and run. The Excel JavaScript API is fundamentally batch-centric. You can queue up as many changes as you wish on the request context, and then call the sync() method to run the batch of queued commands.

Например, во фрагменте кода ниже показано, как объявить локальный объект JavaScript selectedRange для ссылки на выделенный диапазон в документе Excel, а затем задать ряд свойств для этого объекта. Объект selectedRange представляет собой прокси-объект, поэтому свойства, заданные в этом объекте, и методы, вызванные в этом объекте, не будут отображены в документе Excel, пока надстройка не вызовет метод context.sync().For example, the following code snippet declares the local JavaScript object selectedRange to reference a selected range in the Excel document, and then sets some properties on that object. The selectedRange object is a proxy object, so the properties that are set and method that is invoked on that object will not be reflected in the Excel document until your add-in calls context.sync().

var selectedRange = context.workbook.getSelectedRange();
selectedRange.format.fill.color = "#4472C4";
selectedRange.format.font.color = "white";
selectedRange.format.autofitColumns();

sync()sync()

При вызове метода sync() в контексте запроса будет синхронизировано состояние прокси-объектов и объектов в документе Excel. Метод sync() запускает любые команды, помещенные в очередь в контексте запроса, и получает значения для любых свойств, которые следует загрузить, в прокси-объектах. Метод sync() выполняется асинхронно и возвращает обещание, которое разрешается по завершении работы метода sync().Calling the sync() method on the request context synchronizes the state between proxy objects and objects in the Excel document. The sync() method runs any commands that are queued on the request context and retrieves values for any properties that should be loaded on the proxy objects. The sync() method executes asynchronously and returns a promise, which is resolved when the sync() method completes.

В примере ниже показана пакетная функция, которая определяет локальный прокси-объект JavaScript (selectedRange), загружает свойство этого объекта, а затем использует шаблон JavaScript Promises для вызова метода context.sync() и, соответственно, синхронизации состояния прокси-объектов и объектов в документе Excel.The following example shows a batch function that defines a local JavaScript proxy object (selectedRange), loads a property of that object, and then uses the JavaScript Promises pattern to call context.sync() to synchronize the state between proxy objects and objects in the Excel document.

Excel.run(function (context) {
    var selectedRange = context.workbook.getSelectedRange();
    selectedRange.load('address');
    return context.sync()
      .then(function () {
        console.log('The selected range is: ' + selectedRange.address);
    });
}).catch(function (error) {
    console.log('error: ' + error);
    if (error instanceof OfficeExtension.Error) {
        console.log('Debug info: ' + JSON.stringify(error.debugInfo));
    }
});

В предыдущем примере при вызове метода context.sync() задается объект selectedRange и загружается его свойство address.In the previous example, selectedRange is set and its address property is loaded when context.sync() is called.

Так как sync()  — асинхронная операция, возвращающая обещание, вам всегда следует возвращать обещание (в JavaScript).Because sync() is an asynchronous operation that returns a promise, you should always return the promise (in JavaScript). Это гарантирует, что операция sync() будет завершена до того как продолжится выполнение скрипта.Doing so ensures that the sync() operation completes before the script continues to run. Дополнительные сведения об оптимизации производительности с помощью метода sync() см. в статье Оптимизация производительности API JavaScript для Excel.For more information about optimizing performance with sync(), see Excel JavaScript API performance optimization.

load()load()

Чтобы можно было считывать свойства прокси-объекта, вам необходимо явно загрузить их и заполнить прокси-объект данными из документа Excel, а затем вызвать метод context.sync(). Например, вы создали прокси-объект для ссылки на выделенный диапазон, а затем вам потребовалось считать свойство address выделенного диапазона. Прежде чем вы сможете считать свойство address, вам потребуется загрузить его. Чтобы запросить загрузку свойств прокси-объекта, вызовите метод load() в объекте и укажите свойства, которые необходимо загрузить.Before you can read the properties of a proxy object, you must explicitly load the properties to populate the proxy object with data from the Excel document, and then call context.sync(). For example, if you create a proxy object to reference a selected range, and then want to read the selected range's address property, you need to load the address property before you can read it. To request properties of a proxy object be loaded, call the load() method on the object and specify the properties to load.

Примечание

Если вы вызываете методы или задаете свойства только в прокси-объекте, вам не нужно вызывать объект load(). Метод load() требуется только тогда, когда вам необходимо считать свойства в прокси-объекте.If you are only calling methods or setting properties on a proxy object, you do not need to call the load() method. The load() method is only required when you want to read properties on a proxy object.

Аналогично запросам для задания свойств или вызова методов в прокси-объектах, запросы на загрузку свойств в прокси-объектах добавляются в очередь команд, ожидающих выполнения, в контексте запроса, который будет запущен, когда вы в следующий раз вызовете метод sync(). В очередь можно поставить сколько угодно вызовов load() в контексте запроса.Just like requests to set properties or invoke methods on proxy objects, requests to load properties on proxy objects get added to the queue of pending commands on the request context, which will run the next time you call the sync() method. You can queue up as many load() calls on the request context as necessary.

В примере ниже загружаются только определенные свойства диапазона.In the following example, only specific properties of the range are loaded.

Excel.run(function (context) {
    var sheetName = 'Sheet1';
    var rangeAddress = 'A1:B2';
    var myRange = context.workbook.worksheets.getItem(sheetName).getRange(rangeAddress);

    myRange.load(['address', 'format/*', 'format/fill', 'entireRow' ]);

    return context.sync()
      .then(function () {
        console.log (myRange.address);              // ok
        console.log (myRange.format.wrapText);      // ok
        console.log (myRange.format.fill.color);    // ok
        //console.log (myRange.format.font.color);  // not ok as it was not loaded
        });
    }).then(function () {
        console.log('done');
}).catch(function (error) {
    console.log('Error: ' + error);
    if (error instanceof OfficeExtension.Error) {
        console.log('Debug info: ' + JSON.stringify(error.debugInfo));
    }
});

Так как в предыдущем примере в вызове метода myRange.load() не указан format/font, вам не удастся считать свойство format.font.color.In the previous example, because format/font is not specified in the call to myRange.load(), the format.font.color property cannot be read.

Чтобы оптимизировать производительность, при использовании метода load() в объекте вам следует явно указать свойства и связи, которые необходимо загрузить, как описано в статье Оптимизация производительности API JavaScript для Excel.To optimize performance, you should explicitly specify the properties and relationships to load when using the load() method on an object, as covered in Excel JavaScript API performance optimizations. Дополнительные сведения о методе load() см. в статье Дополнительные концепции программирования с помощью API JavaScript для Excel.For more information about the load() method, see Advanced programming concepts with the Excel JavaScript API.

Значения null или пустые значения свойствnull or blank property values

Входное значение null в двумерном массивеnull input in 2-D Array

В Excel диапазон представлен двумерным массивом, в котором первое измерение — это строки, а второе — столбцы. Чтобы задать значения, формат чисел или формулу только для определенных ячеек в диапазоне, укажите значения, формат чисел или формулу для этих ячеек в двумерном массиве, а для всех остальных ячеек в этом массиве укажите значение null.In Excel, a range is represented by a 2-D array, where the first dimension is rows and the second dimension is columns. To set values, number format, or formula for only specific cells within a range, specify the values, number format, or formula for those cells in the 2-D array, and specify null for all other cells in the 2-D array.

Например, чтобы изменить формат чисел только для одной ячейки в диапазоне и сохранить существующий формат чисел для всех остальных ячеек в диапазоне, укажите новый формат чисел для ячейки, которую необходимо изменить, а для всех остальных ячеек укажите значение null. Во фрагменте кода ниже показано, как задать новый формат чисел для четвертой ячейки в диапазоне, при этом формат чисел для первых трех ячеек в диапазоне останется неизменным.For example, to update the number format for only one cell within a range, and retain the existing number format for all other cells in the range, specify the new number format for the cell to update, and specify null for all other cells. The following code snippet sets a new number format for the fourth cell in the range, and leaves the number format unchanged for the first three cells in the range.

range.values = [['Eurasia', '29.96', '0.25', '15-Feb' ]];
range.numberFormat = [[null, null, null, 'm/d/yyyy;@']];

Входное значение null для свойстваnull input for a property

null не является допустимым входным значением для одного свойства. Например, указанный ниже фрагмент кода не является допустимым, так как свойство values диапазона не должно иметь значение null.null is not a valid input for single property. For example, the following code snippet is not valid, as the values property of the range cannot be set to null.

range.values = null;

Аналогично, указанный ниже фрагмент кода не является допустимым, так как null — недопустимое значение для свойства color.Likewise, the following code snippet is not valid, as null is not a valid value for the color property.

range.format.fill.color =  null;

Значения свойств null в ответеnull property values in the response

Если в указанном диапазоне имеются другие значения, свойства форматирования, например size и color будут содержать значения null в ответе. Например, если вы получаете диапазон и загружаете его свойство format.font.color:Formatting properties such as size and color will contain null values in the response when different values exist in the specified range. For example, if you retrieve a range and load its format.font.color property:

  • Если у всех ячеек в диапазоне один и тот же цвет шрифта, свойство range.format.font.color указывает этот цвет.If all cells in the range have the same font color, range.format.font.color specifies that color.
  • Если в диапазоне используется несколько цветов шрифтов, свойство range.format.font.color имеет значение null.If multiple font colors are present within the range, range.format.font.color is null.

Пустое входное значение для свойстваBlank input for a property

Когда вы указываете пустое значение для свойства (то есть две кавычки подряд без других знаков между ''), это будет интерпретировано как инструкция по очистке или сбросу свойства. Например:When you specify a blank value for a property (i.e., two quotation marks with no space in-between ''), it will be interpreted as an instruction to clear or reset the property. For example:

  • Если вы укажете пустое значение для свойства values диапазона, содержимое диапазона будет очищено.If you specify a blank value for the values property of a range, the content of the range is cleared.

  • Если вы укажете пустое значение для свойства numberFormat, формат чисел будет "сброшен" до формата General.If you specify a blank value for the numberFormat property, the number format is reset to General.

  • Если вы укажете пустое значение для свойств formula и formulaLocale, значения формул будут очищены.If you specify a blank value for the formula property and formulaLocale property, the formula values are cleared.

Значения пустых свойств в ответеBlank property values in the response

Для операций чтения пустое значение свойства в ответе (то есть две кавычки подряд без других знаков между '') указывает, что ячейка не содержит данных или значения. В первом примере ниже первая и последняя ячейки в диапазоне не содержат данных. Во втором примере две первые ячейки в диапазоне не содержат формул.For read operations, a blank property value in the response (i.e., two quotation marks with no space in-between '') indicates that cell contains no data or value. In the first example below, the first and last cell in the range contain no data. In the second example, the first two cells in the range do not contain a formula.

range.values = [['', 'some', 'data', 'in', 'other', 'cells', '']];
range.formula = [['', '', '=Rand()']];

Чтение из неограниченного диапазона и запись в негоRead or write to an unbounded range

Чтение из неограниченного диапазонаRead an unbounded range

Адрес неограниченного диапазона представляет собой адрес диапазона, указывающий весь столбец (столбцы) либо всю строку (строки). Например:An unbounded range address is a range address that specifies either entire column(s) or entire row(s). For example:

  • Адреса диапазона включают в себя весь столбец (столбцы):Range addresses comprised of entire column(s):
    • C:C
    • A:F
  • Адреса диапазона включают в себя всю строку (строки):Range addresses comprised of entire row(s):
    • 2:2
    • 1:4

Когда API отправляет запрос на получение неограниченного диапазона (например, getRange('C:C')), ответ будет содержать значения null для свойств уровня ячейки, например свойств values, text, numberFormat и formula. Другие свойства диапазона, например address и cellCount, будут содержать допустимые значения для неограниченного диапазона.When the API makes a request to retrieve an unbounded range (for example, getRange('C:C')), the response will contain null values for cell-level properties such as values, text, numberFormat, and formula. Other properties of the range, such as address and cellCount, will contain valid values for the unbounded range.

Запись в неограниченный диапазонWrite to an unbounded range

Вам не удастся задать свойства уровня ячейки, например values, numberFormat и formula, в неограниченном диапазоне, так как входной запрос слишком велик. Например, приведенный ниже фрагмент кода недопустим, так как он пытается указать свойство values для неограниченного диапазона. Если вы попытаетесь задать свойства уровня ячейки для неограниченного диапазона, API возвратит ошибку.You cannot set cell-level properties such as values, numberFormat, and formula on unbounded range because the input request is too large. For example, the following code snippet is not valid because it attempts to specify values for an unbounded range. The API will return an error if you attempt to set cell-level properties for an unbounded range.

var range = context.workbook.worksheets.getActiveWorksheet().getRange('A:B');
range.values = 'Due Date';

Чтение из большого диапазона и запись в негоRead or write to a large range

Если диапазон содержит большое количество ячеек, значений, форматов чисел или формул, то, возможно, не удастся выполнить операции API над этим диапазоном. API всегда делает все возможное, чтобы выполнить запрошенную операцию над диапазоном (то есть получить или записать указанные данные), но попытка выполнить операцию чтения или записи для большого диапазона может привести к ошибке API из-за чрезмерного потребления ресурсов. Чтобы избежать таких ошибок, мы рекомендуем выполнять отдельные операции чтения или записи для небольших подмножеств большого диапазона, а не пытаться выполнить одну операцию чтения или записи для большого диапазона.If a range contains a large number of cells, values, number formats, and/or formulas, it may not be possible to run API operations on that range. The API will always make a best attempt to run the requested operation on a range (i.e., to retrieve or write the specified data), but attempting to perform read or write operations for a large range may result in an API error due to excessive resource utilization. To avoid such errors, we recommend that you run separate read or write operations for smaller subsets of a large range, instead of attempting to run a single read or write operation on a large range.

Важно!

В Excel в Интернете действует ограничение в 5 МБ на размер полезных данных запросов и откликов.Excel Online has a payload size limit for requests and responses of 5MB. При превышении этого ограничения возникает ошибка RichAPI.Error.RichAPI.Error will be thrown if that limit is exceeded.

Изменение всех ячеек в диапазонеUpdate all cells in a range

Если необходимо одинаково изменить все ячейки в диапазоне (например, заполнить все ячейки одним и тем же значением или формулой либо задать один и тот же формат чисел), задайте для соответствующего свойства в объекте range (одно) необходимое значение.To apply the same update to all cells in a range, (for example, to populate all cells with the same value, set the same number format, or populate all cells with the same formula), set the corresponding property on the range object to the desired (single) value.

В примере ниже показано, как получить диапазон, содержащий 20 ячеек, а затем задать формат чисел и заполнить все ячейки в диапазоне значением 3/11/2015 (11.03.2015).The following example gets a range that contains 20 cells, and then sets the number format and populates all cells in the range with the value 3/11/2015.

Excel.run(function (context) {
    var sheetName = 'Sheet1';
    var rangeAddress = 'A1:A20';
    var worksheet = context.workbook.worksheets.getItem(sheetName);

    var range = worksheet.getRange(rangeAddress);
    range.numberFormat = 'm/d/yyyy';
    range.values = '3/11/2015';
    range.load('text');

    return context.sync()
      .then(function () {
        console.log(range.text);
    });
}).catch(function (error) {
    console.log('Error: ' + error);
    if (error instanceof OfficeExtension.Error) {
      console.log('Debug info: ' + JSON.stringify(error.debugInfo));
    }
});

Обработка ошибокHandle errors

При возникновении ошибки в интерфейсе API он возвращает объект error, содержащий код и сообщение.When an API error occurs, the API returns an error object that contains a code and a message. Подробные сведения об обработке ошибок, включая список ошибок API, см. в статье Обработка ошибок.For detailed information about error handling, including a list of API errors, see Error handling.

См. такжеSee also