Создайте и используйте пользовательское средство поиска

API генерации отчета MATLAB Report Generator поддерживает создание средств поиска, которые ищут контейнеры данных заданные объекты и возвращают результаты в заслуживающей публикации форме. Средства поиска позволяют вам разделять поисковую логику от логики отчета в ваших генераторах отчетов. Средства поиска также способствуют повторному использованию поисковой логики, таким образом, ускоряя разработку генераторов отчетов. Этот пример показывает, как разработать и использовать средство поиска, чтобы сгенерировать отчет.

Задайте средство поиска

Создание средства поиска влечет за собой создание класса MATLAB, который задает свойства и поведение средства поиска. Следующие разделы объясняют, что шаги должны были создать класс средства поиска. Объяснение использует класс под названием GrantFinder as an example. Код для класса находится в файле, GrantFinder.m, который сопровождает этот скрипт. Класс GrantFinder задает средство поиска, способное к нахождению и форматированию грантов, предоставленных американским Национальным фондом гуманитарных наук (NEH).

Создайте скелетный файл определения класса

Используйте редактора MATLAB (не Live Editor), чтобы создать скелетное определение класса для вашего средства поиска, например

Задайте базовый класс средства поиска

Задайте API Отчета класс mlreportgen.finder.Finder как базовый класс для вашего средства поиска.

Этот базовый класс задает свойства, которые характерны для средств поиска, включая

  • Container: свойство раньше ссылалось на контейнер, который будет искаться средством поиска. Например, GrantFinder используют это свойство сохранить ссылку на базу данных предоставления, которую это создает.

  • Свойства: свойство, используемое клиентами средства поиска, чтобы задать значения свойств, что объекту, должно быть, придется удовлетворить поиск. Например, это свойство позволяет клиенту GrantFinder задавать свойства предоставления, что предоставление, должно быть, придется возвратить в результате поиска базы данных предоставления NEH.

Класс mlreportgen.finder.Finder задает другие свойства и методы, которые должно задать ваше определение класса средства поиска. Это гарантирует, что ваше средство поиска работает с API Отчета.

Задайте конструктора средства поиска

Задайте функцию, которая создает экземпляр вашего средства поиска, например,

Конструктор GrantFinder использует функцию xmlread MATLAB, чтобы считать XML-файл предоставления из диска и преобразовать его в Java документ DOM. Это затем передает документ DOM конструктору mlreportgen.finder.Finder, который устанавливает Java документ DOM как значение свойства Container средства поиска. При хранении базы данных NEH как Java документ DOM позволяет средству поиска использовать стороннее программное обеспечение Java, чтобы искать базу данных. См. Java Xerces API DOM для получения дополнительной информации.

Конструктор также вызывает функцию reset, которая инициализирует переменные, используемые, чтобы искать базу данных предоставления. Класс GrantFinder задает эту функцию. Точно так же ваш класс должен задать функцию сброса. Функция reset гарантирует, что клиент может использовать ваше средство поиска, чтобы провести несколько поисковых запросов его контейнера. Смотрите Задают Функцию Сброса для получения дополнительной информации.

Задайте метод find

Задайте метод, чтобы искать контейнер средства поиска объекты, которые соответствуют заданным пользователями ограничениям. Метод находки должен возвратить массив объектов результата, которые содержат объекты, которые он находит. Объекты результата являются объектами базового типа mlreportgen.finder.Result. Возврат результатов находки как объекты результата позволяет пользователю вашего средства поиска добавлять результаты в главу отчета или отчета. Смотрите Задают Результат Средства поиска для получения дополнительной информации. Возврат результатов находки как массив MATLAB позволяет вам использовать цикл for, чтобы обработать результаты поиска, например

Метод find GrantFinder иллюстрирует определение метода find.

Этот метод находки использует getNodeList, поисковая служебная функция, которую задает класс GrantFinder (см., Задает Поисковый Служебный метод) искать базу данных предоставления предоставления, которые соответствуют ограничениям значения свойства, заданным свойством Properties средства поиска. Функция getNodeList устанавливает внутреннее свойство под названием NodeList к результату его поиска. Результатом является объект Java DOM NodeList (NodeList), который содержит результаты поиска как список Java элементы DOM (Element).

Метод find затем преобразовывает этот список узлов в массив объектов результата типа GrantResult. Это использует конструктора GrantResult, чтобы создать объект результата предоставления из объекта Java DOM Element, который содержит данные о предоставлении.

Define hasNext и методы next

Ваше определение класса средства поиска должно задать методы next и hasNext. На его первом вызове ваш метод hasNext должен создать очередь результатов поиска и возвратить true, если очередь не пуста. На последующих вызовах метод hasNext должен возвратить true, если очередь пуста, false в противном случае. Ваш метод next должен возвратить первый результат в очереди на ее первом вызове, следующий результат, на ее следующем вызове, и так далее, пока очередь не пуста.

Эти методы предназначаются, чтобы позволить клиенту вашего средства поиска использовать цикл while MATLAB, чтобы искать контейнер вашего средства поиска, например,

Класс GrantFinder иллюстрирует метод hasNext.

Этот метод сначала проверяет, создал ли он уже поисковую очередь, как обозначено свойством IsIterating средства поиска. Если очередь уже существует и не пуста, этот метод возвращает true. если очередь существует и пуста, этот метод возвращает false. Если очередь еще не существует (т.е. это - первый вызов метода), метод hasNext создает очередь результата можно следующим образом. Во-первых, это использует свой внутренний метод getNodeList, чтобы получить предоставления, которые соответствуют критериям поиска, заданным свойством Properties средства поиска. Метод getNodeList устанавливает внутреннее свойство средства поиска под названием NodeCount к количеству найденных результатов. Если NodeCount больше, чем нуль, метод hasNext устанавливает внутреннее свойство под названием NextNodeIndex к 1. Метод next средства поиска использует это свойство сохранить состояние поисковой очереди, которая является следующим элементом в очереди. Наконец, если очередь не первоначально пуста, средство поиска возвращает true; в противном случае, false.

Метод next GrantFinder работает с очередью, созданной методом hasNext.

Задайте поисковый служебный метод

find вашего средства поиска и методы hasNext должны искать контейнер вашего средства поиска объекты, которые удовлетворяют поисковые ограничения. Необходимо рассмотреть определение поисковой утилиты, которую могут использовать оба метода. Например, hasNext GrantFinder и методы next оба делегата, ищущие на внутреннюю утилиту под названием getNodeList. Метод getNodeList в свою очередь делегирует поиск к API поиска XML-документа под названием XPath (см. Начало работы с XPath).

Создайте свойство InvalidPropertyNames

Ваше средство поиска должно задать свойство под названием InvalidPropertyNames, который задает свойства объектов, которые не могут использоваться, чтобы ограничить поиск. Базовый класс mlreportgen.finder.Finder использует это свойство проверить, что заданные пользователями поисковые свойства, заданные свойством Properties вашего средства поиска, допустимы. В противном случае базовый класс выдает ошибку. Другими словами, если клиент устанавливает свойство Properties вашего средства поиска на недопустимые свойства, базовый класс выдает ошибку. Таким образом основное средство поиска API Отчета обрабатывает проверку валидности свойства ваше средство поиска.

Если ваше средство поиска может использовать какое-либо поисковое свойство объекта в качестве поискового ограничения, это должно установить пустое свойство InvalidPropertyNames. Например, GrantFinder может обработать любое свойство предоставления. Это поэтому устанавливает это пустое свойство:

Задайте метод reset

Средство поиска должно смочь поддержать несколько поисковых запросов, чтобы избежать потребности создать средство поиска для каждого поиска. Поэтому основной класс средства поиска API Отчета обеспечивает ваш класс средства поиска, чтобы задать метод reset, который сбрасывает переменные, используемые поисковой логикой вашего средства поиска, например,

Задайте результат средства поиска

Если подходящее определение не существует, необходимо создать класс, чтобы задать объекты результата, возвращенные средством поиска. Этот раздел показывает, как задать объект результата средства поиска. Это использует класс под названием GrantResult как пример. Класс GrantResult задает результаты, возвращенные классом GrantFinder, используемым в качестве примера в разделе Define a Finder. Файл GrantResult.m, который сопровождает этот скрипт, содержит код для класса GrantResult. Определение результата средства поиска влечет за собой следующие задачи.

Задайте базовый класс результата

Задайте mlreportgen.finder.Result как базовый класс для вашего класса результата, например,

Задайте свойство Object

Задайте свойство под названием Object, который клиенты вашего объекта результата могут использовать, чтобы получить доступ к найденному объекту, который содержит ваш объект результата. Задайте protected как значение SetAccess свойства Object вашего средства поиска. Это гарантирует, что только ваш результат может задать найденный объект, который он содержит.

Ваш конструктор результата должен установить найденный объект как значение его свойства Object. Ваш конструктор результата может использовать конструктора базового класса, чтобы выполнить эту задачу, например,

Представьте найденные свойства объектов

Свойство Object вашего результата позволяет клиенту получать доступ к найденному объекту и поэтому его свойствам. Однако доступ к свойствам может требовать дополнительного кода или специализированных знаний. Можно хотеть представить некоторых или все свойства найденного объекта как свойства объекта результата. Например, класс GrantResult представляет следующее подмножество свойств предоставления.

Это сохраняет клиент объекта результата средства поиска предоставления от необходимости извлечь эти свойства самой. Конструктор вашего результата должен извлечь значения свойств, которые будут представлены, и установил соответствующие свойства результата на извлеченные значения, например,

Обратите внимание на то, что GrantResult комбинирует некоторые свойства предоставления в одно представленное свойство. Например, это представляет InstCity предоставления, InstState, InstPostalCode и свойства InstCountry в одно свойство результата под названием Location.

В этом примере конструктор использует внутренние методы, чтобы извлечь свойства предоставления от объекта предоставления, который является объектом Java DOM Element, например,

Задайте метод getReporter

Необходимо задать getReporter метод для объекта результата, который возвращается, генератор отчетов возражают, что отчеты относительно найденного объекта, что объект результата содержит. Этот метод позволяет клиенту вашего средства поиска сообщать относительно результата операции находки просто путем добавления результата в Report, Section или объект Chapter. Например,

Отчет или метод add главы знают, что объект результата должен иметь метод getReporter, который возвращает генератор отчетов, который форматирует данные, которые содержит результат. Таким образом, если вы добавляете объект результата в отчет или главу, метод add вызывает метод getReporter результата, чтобы получить генератор отчетов результата и добавляет генератор отчетов результата в отчет или генератор отчетов, заставляя данные о результате быть отформатированным и включенным в отчет.

Определение класса GrantResult задает метод getReporter, который возвращает настроенную версию API Отчета генератор отчетов mlreportgen.report.BaseTable. Генератор отчетов BaseTable генерирует таблицу с пронумерованным заголовком. Класс GrantResult настраивает генератор отчетов BaseTable, чтобы сгенерировать таблицу свойств предоставления, например,

Следующий код показывает, как класс GrantResult настраивает BaseReporter, чтобы сгенерировать пронумерованную таблицу свойств предоставления:

Используйте средство поиска

Этот скрипт показывает, как использовать средство поиска, чтобы сгенерировать отчет. Этот скрипт использует пример GrantFinder, используемый в разделе Define a Finder, чтобы сгенерировать отчет PDF относительно предоставлений NEH к учреждениям в выбранных состояниях от 2 010 до 2012. Скрипт выполняет следующие задачи.

Импортируйте API генератора отчетов

Импортируйте классы, включенные в API Отчета MATLAB Report Generator. Импорт классов позволяет скрипту использовать дисквалифицированный (т.е. сокращенный) имена, чтобы относиться к классам.

import mlreportgen.report.*
import mlreportgen.dom.*

Создайте контейнер отчета

Создайте контейнер PDF для отчета, с помощью API Отчета класс mlreportgen.report.Report. Обратите внимание на то, что, потому что скрипт импортирует API Отчета, он может относиться к классу своим неполным именем.

rpt = Report('grant', 'pdf');

Создайте титульный лист отчета

Добавьте титульный лист в отчет, с помощью API Отчета класс TitlePage.

add(rpt, TitlePage( ...
    'Title', 'NEH Grants', ...
    'Subtitle', 'By State from 2010-2012', ...
     'Image', 'neh_logo.jpg', ...
     'Author',  'John Doe' ...
    ));

Создайте оглавление отчета

Добавьте оглавление, с помощью API Отчета класс TableOfContents.

add(rpt, TableOfContents);

Найдите данные об отчете

Используйте массив структур, чтобы задать состояния, которые будут включены в этот отчет. Каждая структура содержит данные для определенного состояния:

  • Имя: имя состояния

  • PostalCode: состояние, почтовое (zip) код

  • Grants: предоставления, сделанные к учреждениям в состоянии. Это поле первоначально пусто.

  • NGrants: количество предоставлений, сделанных к учреждениям в этом состоянии (первоначально пустой)

states = struct( ...
    'Name', {'California', 'Massachusetts', 'New York'}, ...
    'PostalCode', {'CA', 'MA', 'NY'}, ...
    'Grants', cell(1,3), ...
    'NGrants', cell(1,3) ...
    );

Используйте средство поиска предоставления, чтобы заполнить поля Grants и NGrants структур состояния. Создайте средство поиска предоставления.

f = GrantFinder;

Цикл через массив состояния. Для каждого состояния используйте свойство Properties средства поиска ограничить поиск грантов, предоставленных состоянию. Используйте эти свойства предоставления ограничить поиск:

  • InstState: Задает индекс состояния, в который учреждение, которое получило предоставление, расположен.

  • YearAwarded: Задает год, в котором был предоставлен грант.

Средство поиска обрабатывает значения свойств как регулярные выражения. Используйте этот факт, чтобы задать область значений значений, 2010-2012, как значение свойства YearAwarded.

n = numel(states);
for i = 1:n    
    f.Properties = [
        {'InstState', states(i).PostalCode}, ...       
        {'YearAwarded', '201[0-2]'}];
    states(i).Grants = find(f);
    states(i).NGrants = numel(states(i).Grants);
end

Создайте главу сводных данных предоставления

Создайте сводные данные предоставления как первую главу отчета. Глава сводных данных предоставления содержит заголовок и сводную таблицу предоставления. Каждая строка таблицы перечисляет общее количество предоставлений и общей суммы денег, присужденных учреждениям в состоянии в течение лет 2010-2012. Состояния появляются в таблице в порядке убывания количества предоставлений. Каждое состояние связывается гиперссылками к главе, которая детализирует гранты, предоставленные ему.

Создайте итоговый контейнер главы

Запустите путем создания контейнера главы..

ch = Chapter('Title', 'Grant Summary');

Создайте содержимое сводной таблицы предоставления

Запустите путем создания средства форматирования валюты Java. Используйте этот объект отформатировать сумму в долларах грантов, предоставленных состоянию.

currencyFormatter = java.text.NumberFormat.getCurrencyInstance();

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

header = {'State', 'Grants Awarded', 'Amount Awarded'};

Предварительно выделите массив ячеек, чтобы содержать табличное содержимое тела. Массив ячеек имеет строки и столбцы Rx3, где R является количеством состояний, и 3 количество итоговых элементов, о которых сообщают для каждого состояния.

body = cell(numel(states), 3);

Сортировка массива состояний количеством грантов, предоставленных им, с помощью функции sort MATLAB. Функция sort возвращает ind, массив индексов к массиву состояний. Первый индекс массива ind является индексом состояния с большинством предоставлений, вторым, со вторым самым большим количеством предоставлений, и т.д.

[~, ind] = sort([states.NGrants], 'descend');

Цикл через состояния количеством предоставлений, заполняя итоговую информацию для каждого состояния. Используйте переменную, rowIdx, как индекс к строке массива ячеек, соответствующей текущему состоянию.

rowIdx = 0;

Следующая строка перестраивает массив states в порядке полученных предоставлений и создает цикл for, который присваивает каждую структуру в отсортированном массиве states к переменной state на каждой итерации цикла.

for state = states(ind)

Обновите индекс строки, чтобы указать на строку массива ячеек, соответствующую текущему состоянию.

    rowIdx = rowIdx+1; 

Скрипт вводит гиперссылку на главу деталей предоставления для состояния как первая запись в таблице для состояния, например,

Следующая строка использует конструктора InternalLink DOM, чтобы создать гиперссылку. Конструктор InternalLink берет два аргумента, ID цели ссылки и текст гиперссылки. Скрипт использует индекс текущего состояния в качестве ID цели ссылки и имени состояния как текст ссылки. Позже, когда скрипт создает главу деталей предоставления, он вставляет цель ссылки в заголовок главы, ID которого является индексом состояния. Это завершает создание гиперссылки.

    body(rowIdx, 1) = {InternalLink(state.PostalCode, state.Name)};

Присвойте общий номер предоставлений на это состояние к второму элементу в его строке массива ячеек.

    body(rowIdx, 2) = {state.NGrants};
    

Вычислите общую сумму, присужденную этому состоянию.

    totalAwarded = 0;
    for grant = state.Grants
        totalAwarded = totalAwarded + str2double(grant.AwardAmount);
    end
    

Используйте средство форматирования валюты, чтобы отформатировать общую сумму как сумму в долларах, например,

и присвойте результат форматирования как третий и итоговый элемент в массиве ячеек для этого состояния.

    body(rowIdx,3) = {char(currencyFormatter.format(totalAwarded))};
end

Чтобы составить сводную таблицу, передайте ячейку заголовка и массивы ячейки основной области конструктору объекта mlreportgen.dom.FormalTable.

table = FormalTable(header, body);

Формальная таблица является таблицей, которая имеет заголовок и тело. Конструктор FormalTable берет два аргумента: массив ячеек, который задает содержимое заголовка таблицы и массива ячеек, который задает содержимое его тела. Конструктор преобразовывает содержимое массива ячеек в TableRow DOM и объекты TableEntry, которые задают таблицу, избавляя скрипт от необходимости создать необходимые объекты таблицы самой.

Отформатируйте сводную таблицу предоставления

На данном этапе сводная таблица выглядит так:

Это не очень читаемо. Заголовок имеет тот же формат как тело, и столбцы не расположены с интервалами независимо.

В следующих шагах скрипт настраивает форматирование текста заголовка, чтобы выглядеть так:

Сначала скрипт задает ширину и выравнивание столбцов таблицы, с помощью объекта DOM TableColSpecGroup. Объект TableColSpecGroup задает формат группы столбцов. Сводная таблица имеет только одну группу столбцов, таким образом, скрипт должен создать только один объект TableColSpecGroup.

grp = TableColSpecGroup;

Объект TableColSpecGroup позволяет скрипту задать стиль по умолчанию столбцов таблицы. Скрипт задает 1.5in как ширину по умолчанию столбцов и выравнивания по центру как выравнивание столбца по умолчанию.

grp.Style = {HAlign('center'), Width('1.5in')};

Скрипт использует объект TableColSpec заменить выравнивание столбца по умолчанию для первого столбца.

specs(1) = TableColSpec;
specs(1).Style = {HAlign('left')};
grp.ColSpecs = specs;
table.ColSpecGroups = grp;

Обратите внимание, что скрипт мог использовать целых три объекта TableColSpec, один для каждого столбца таблицы, чтобы заменить стили столбца группы. Первый объект TableColSpec применяется к первому столбцу, второму к второму столбцу, и т.д. Скрипт должен присвоить только один объект спецификации столбца группе, потому что это заменяет стиль по умолчанию только для первого столбца. Однако, если бы это должно было изменить только третий столбец, это должно было бы присвоить три объекта спецификации столбца, оставив свойство Style первых двух объектов спецификации столбца пустым.

Стиль таблицы по умолчанию переполняет записи таблицы. Таким образом, скрипт использует объект формата InnerMargin DOM, чтобы создать некоторое пространство выше записей, чтобы разделить их от записей в строке выше их. Объект InnerMargin создает пространство (внутреннее поле) между объектом документа и объектом, который содержит его, например, между текстом в записи таблицы и границами записи таблицы. Конструктор InnerMargin опционально берет четыре аргумента, левых, право, верхнюю часть, нижняя часть внутренние поля объекта документа.

Использование скрипта этот конструктор, чтобы создать главный внутренний граничный формат 3 точек. Это затем присваивает этот формат стилю записей в разделе тела сводной таблицы.

table.Body.TableEntriesStyle = {InnerMargin('0pt', '0pt', '3pt', '0pt')};

Наконец скрипт форматирует табличный заголовок, чтобы состоять из полужирного, белого текста на сером фоне:

table.Header.row(1).Style = {Bold, Color('white'), BackgroundColor('gray')}; 

Добавьте итоговую главу в отчет

add(ch, table);

add(rpt, ch);

Создайте главы деталей предоставления

Цикл через структуры состояния.

for state = states
    

Поскольку каждое состояние создает главу, чтобы содержать детали предоставления состояния. Вставьте цель ссылки в заголовок главы, чтобы служить целью для гиперссылки в сводной таблице в первой главе.

    ch = Chapter('Title', {LinkTarget(state.PostalCode), state.Name});
    

Цикл через предоставление заканчивается для состояния.

    for grant = state.Grants
        

Для каждого результата предоставления добавьте результат в главу.

        add(ch, grant);

Результат предоставления имеет метод getReporter, который возвращает генератор отчетов, который составляет таблицу выбранных свойств предоставления. Глава метод add предварительно сконфигурирована, чтобы получить генератор отчетов результата и добавить его глава. Таким образом добавление предоставления к главе эквивалентно добавлению таблицы свойства результата к главе, например,

    end
    add(rpt, ch);
end  

Закройте объект отчета

Закрытие объекта отчета генерирует выходной файл PDF (grant.pdf), который задает объект отчета.

close(rpt);

Отобразите отчет

rptview(rpt);

Приложение: база данных предоставления NEH

Источником базы данных, используемой в этом примере, является Национальный фонд гуманитарных наук (NEH). База данных содержит информацию о предоставлениях NEH на период 2010-2019. Это содержит приблизительно 6 000 записей в формате XML. Это доступно в Данных о Предоставлении NEH. Этот пример использует локальную копию XML-файла базы данных, NEH_Grants2010s.xml.

База данных состоит из элемента Grants, который содержит набор элементов Grant, каждый из которых содержит набор элементов данных предоставления. Следующее является извлечением из базы данных, которая иллюстрирует ее структуру: