Exportação de dados

Alguns tipos de visualização de consultas automatizadas podem ter seu conteúdo exportado para arquivos. Para esses tipos de visualização, é possível determinar formatos de exportação além dos formatos padrão, através da criação de novos processos de exportação.

Construindo um processo de exportação

Para montar um processo de exportação, é necessário incluir nesse processo o script no caminho ufs:/webframework/templates/js/dataexporter.js, através da função __include. Esse script irá adicionar ao processo a lógica necessária para receber os dados de um relatório e escrevê-los em um arquivo.

Estrutura do processo de exportação

Ao incluir o script mencionado, o processo de exportação terá duas grades, chamadas exporter (com as variáveis a usar na exportação) e preview (que contém um campo de texto, com uma prévia do conteúdo a ser gradado no arquivo). Essas grades podem ser editadas no processo de exportação. Além delas, o desenvolvedor também pode criar suas próprias grades.

Campos das grades de exportação

A grade preview possui dois campos:

  • lines - determina a quantidade de linhas da pré-visualização da exportação a serem mostradas na grade, no campo content.

  • content - campo de texto onde será se monta a pré-visualização do conteúdo exportado.

A grade exporter não possui, por conta própria, campos fixos. Seus campos são gerados automaticamente, sendo um campo booleano para cada campo a ser exportado. Dessa forma, o usuário pode indicar quais campos deseja incluir na exportação. Por padrão, todos esses campos se inicializam marcados.

API do processo de exportação

O script mencionado anteriormente também provê os seguintes métodos e propriedades públicos para o processo:

Métodos

  • finishExport - finaliza a exportação e redireciona o usuário para a interação na qual ele poderá baixar o arquivo.
  • getRandomName - gera uma string aleatória, para compor o nome do arquivo;
  • getSelectedFieldIndexes - Obtém os índices dos campos que estão selecionados na grade exporter;
  • updatePreview - Atualiza a grade de pré-visualização do processo;
  • writeGrids - Escreve as grades padrão do processo.

Note que a função getFileName pode ser sobrescrita sem maiores problemas. Ela só precisa retornar uma string.

A seguinte função é virtual e deve ser obrigatoriamente sobrescrita:

  • formatFileContent - deve retornar uma representação textual do conteúdo a ser gravado. Seu conteúdo será exibido na grade de pré-visualização.

Propriedades

  • baseFieldOrder - número base de ordem do qual os campos específicos do processo de exportação devem suceder. Ao criar um campo específico do processo de exportação, sempre defina uma ordem superior a baseOrder, garantindo que os campos definidos sejam exibidos após os campos padrão de qualquer processo de exportação.
  • exportFile - objeto do tipo File, usado para escrever o arquivo com o conteúdo da exportação;
  • exportFilePath - o caminho, no disco, onde o arquivo será escrito;
  • hasPreview - indica se a exportação deve exibir a grade de pré-visualização do conteúdo gerado. Por padrão, seu valor é verdadeiro. Deve ser setado para false caso o conteúdo a exportar seja binário.
  • help - a ajuda do processo. É obrigatório setar esta propriedade. Existe ainda uma propriedade do processo que não é dada pelo script que incluímos, mas sim pelo processo ou relatório de onde vem os dados a serem exportados. Essa propriedade se chama dataExporter e é um objeto da classe DataExporter ou de uma de suas filhas.

Implementando o processo

Após incluso o script já mencionado, devemos implementar no novo processo a interação main. Recomenda-se que as grades padrão sejam exibidas nessa interação.

A partir desse ponto o processo pode utilizar as propriedades e funções publicadas, bem como funcionalidades próprias, para que o usuário possa interagir com o fluxo e para que o arquivo com o conteúdo a exportar seja escrito.

Exemplo de processo de exportação

Segue abaixo um exemplo de código de processo que, dada uma fonte de dados, a exporta para o formato CSV:

/**
 * Exporta dados da grid em formato CSV
 * http://en.wikipedia.org/wiki/Comma-separated_values
 */

__includeOnce('ufs:/goog/array/array.js');
__includeOnce('ufs:/uwl/dataset/dataset.js');
__includeOnce('ufs:/uwl/string/string.js');
__include('ufs:/webframework/templates/js/dataexporter.js');

this.help = 'Este processo converte uma massa de dados para o formato ' +
  'CSV (comma-separated values).';

var fld = this.exporter.field('separator', 'string', 2);
fld.label = 'Separador';
fld.help = 'Indique o separador a ser utilizado para separar os valores';
fld.defaultValue = ';';
fld.required = true;
fld.order = this.baseFieldOrder + 1;
fld.group = "Outras opções de exportação";
fld.onAfterChange.set(function (sender) {
  sender.parent.process.updatePreview();
});

var fld = this.exporter.field('showFieldNamesAtFirstLine', 'boolean');
fld.label = 'Exibe Títulos';
fld.help = 'Marque esta opção caso deseje que a primeira linha do ' +
  'arquivo apresente os nomes das colunas da grid.';
fld.order = this.baseFieldOrder + 2;
fld.group = "Outras opções de exportação";
fld.onAfterChange.set(function (sender) {
  sender.parent.process.updatePreview();
});

this.formatToCSV = function (value) {
  var result = value + '';
  if (result) {
    result = result.replace(" ", " ");
    result = result.replace("<b>", "");
    result = result.replace("</b>", "");
    result = result.replace('"', '""');
    result = '"' + result + '"';
  }
  return result;
};

this.interaction('main', function () {
  inherited();
  this.visibleActions = 'Export';
  this.title = 'Exportar dados para CSV';
  this.writeGrids();
});

/**
 * @override
 */
this.formatFileContent = function (fieldIndexes, opt_linesQty) {
  if (opt_linesQty === 0) {
    return "";
  }
  var result = "";
  var ds = this.dataExporter.dataSet;
  var fieldsToUse = goog.array.map(fieldIndexes, function (index) {
    return this.dataExporter.getField(index);
  }, this);

  if (this.showFieldNamesAtFirstLine) {
    result += goog.array.reduce(fieldsToUse, function (line, fld) {
      line.push(fld.label || fld.name);
      return line;
    }, []).join(this.separator) + "\r\n";
  }

  var status = opt_linesQty ? "Gerando Pré-Visualização" : "Gerando arquivo";
  var totalWork = opt_linesQty || ds.recordCount;
  var progress = new Progress();
  progress.beginTask(status, totalWork);

  for (ds.first(); !ds.eof; ds.next()) {
    result += goog.array.reduce(fieldsToUse, function (line, fld) {
      var value = this.formatToCSV(
        this.dataExporter.formatFieldValue(fld),
        this.exportLookupKeys
      );
      line.push(uwl.string.removeLineBreaks(value));
      return line;
    }, [], this).join(this.separator) + "\r\n";

    progress.worked();

    if (opt_linesQty && ds.recNo == opt_linesQty) {
      break;
    }
  }

  progress.done();

  return result;
};

this.activity('Export', function () {
  this.exportFileName = this.dataExporter.title + '.csv';
  try {
    this.exportFile.write(this.formatFileContent(this.getSelectedFieldIndexes()));
  } finally {
    this.finishExport();
  }
});

Utilizando os novos formatos na exportação da visualização

As visualizações de consultas automatizadas possuem a propriedade extraExportFormats. Essa propriedade é um array de objetos literais, que devem declarar três propriedades:

  • name: o nome do formato de exportação, que será exibido em tela quando o usuário for selecionar um formato;
  • processKey: a chave do processo que implementa a exportação para aquele formato.
  • useRawData: indica se o formato de exportação utiliza os dados “crus” da visualização, isto é, aqueles utilizados para a montagem da exibição. Por padrão é falsa, caso no qual serão utilizados os dados da visualização já transformados e formatados pela visualização.

Caso a propriedade seja declarada na definição de uma visualização, as opções declaradas serão exibidas junto às opções padrão quando o usuário solicitar uma exportação. Quando o usuário selecionar uma dessas opções, será redirecionado ao processo correspondente.

Exemplo

Segue abaixo um exemplo de um script .idsv com a propriedade extraExportFormats declarada:

{
  dataSourceQueryKey: -1892603784, //./Users.idsq */
  type: "report",

  filters: [
    {name: "U_iName", label: "Nome de usuário"}
  ],

  columns: [
    {name: "U_iName", label: "Nome"}
  ],

  extraExportFormats: [
    /* Export to CSV.ip */
    {name: 'CSV', processKey: -1898145324},

    /* Export to EXCEL CSV.ip */
    {name: 'CSV para Excel', processKey: -1898144677},

    {name: 'Formato customizado', processKey: 123456, useRawData: true}
  ]
}