Skip to content

Spreadsheet (Português Brasil)

Ricardo Coelho edited this page Aug 12, 2022 · 11 revisions

Criação de Planilhas (xlsx)

Gerador simplificado de planilhas Excel ou compatíveis.

Começando

Importe a namespace do gerador.

    using BlackDigital.Report;

A classe estática 'ReportGenerator', é onde começa a geração do relatório. A partir dela, chama o builder do relatório de planilhas chamando o método 'Spreadsheet()'.

    ReportGenerator.Spreadsheet()...

A biblioteca BlackDigital.Report utiliza Fluent Interface para construir o relatório.

Atributos do Arquivo

Nome da empresa

Na geração do arquivo de relatório, indicará o nome da empresa.

    ReportGenerator.Spreadsheet()
                   .SetCompany("CompanyName")

Outros

Outros atributos, como autor, não são suportados, indique aqui se há interesse de outros atributos serem adicionados na geração do arquivo.

Criação de Folha de Planilha

Para criar diversas folhas de planilha no mesmo relatório, utilize o método "AddSheet", passando o nome da planilha:

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")

Ao adicionar uma folha de planilha, o Builder irá mudar para que todas as chamadas a seguir sejam criadas dentro dessa folha de planilha, mas é possíve voltar o Builder para a planilha quando desejar chamando o método "Spreadsheet":

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")
                   .Spreadsheet()
                   .AddSheet("Sheet 2")
                   .Spreadsheet()
                   .AddSheet("Sheet 3")

Adição de Valores Básicos

Dentro da folha de planilha, pode adicionar um valor em qualquer célula, para isso utilize o método "AddValue". Pode indicar a célula que irá receber o valor, pela referência ou posição da linha e coluna, mas caso oculte a referência da célula, o valor será adicionado na célula "A1".

Caso seja adicionado dois valores na mesma célula, o último valor adicionado irá sobrepor o valor antigo.

Exemplo o valor adicionando o texto "My Text" na célula B2 pelo código da célula:

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")
                   .AddValue("My Text", "B2")

Exemplo o valor adicionando o data e hora local na célula D3 via número da linha / coluna:

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")
                   .AddValue(DateTime.Now, 4, 3)

Tipos Suportados

C# Type Excel Type Format
string String
short Number
int Number
long Number
float Number
double Number
decimal Number
DateTime Date dd/MM/yyyy HH:mm:ss
DateTimeOffset Date dd/MM/yyyy HH:mm:ss
TimeSpan Number HH:mm:ss
DateOnly* Date dd/MM/yyyy
TimeOnly* Number HH:mm:ss

*Apenas no .NET 6 pra cima

Outros tipos ainda não são suportados, indique aqui se há interesse de outros tipos.

Adição de Fórmulas

Não há suporte para criação de fórmulas, indique aqui se há interesse nisso.

Preenchimento Matrizes Bidimensionais

Dentro da folha de planilha, você pode preencher múltiplos dados de uma só vez usando o método "Fill"

No método Fill pode passar uma matriz bidimensional de object, mas apenas os tipos listados em Tipos Suportados irão aparecer.

É possível indicar a célula que iniciará em receber os valores, pela referência ou posição da linha e coluna, mas caso oculte a referência da célula, os valores iniciarão pela célula "A1".

A primeira matriz, será escrita em cada nova linha e a segunda matriz, será escrito em cada nova coluna.

Exemplo de preenchimento de valores de matrizes bidimensional iniciando na célula B2:

    var list = new List<List<object>>();

    list.Add(new List<object>() { "Line 1", 10, DateTime.Today, TimeSpan.FromHours(3) });
    list.Add(new List<object>() { "Line 2", -10, DateTime.Now, TimeSpan.FromMinutes(12) });
    list.Add(new List<object>() { "Line 3", 10.6m, DateTime.UtcNow, TimeSpan.FromMinutes(45).Add(TimeSpan.FromSeconds(31)) });

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")
                   .Fill(list, "B2")

Preenchimento Lista de Objetos

Dentro da folha de planilha, pode preencher com uma lista de objetos de uma só vez usando o método "FillObject"

No método FillObject passa uma lista de um objeto, onde cada objeto será uma linha e cada propriedade será uma coluna, mas apenas os tipos de propriedades listados em Tipos Suportados irão aparecer.

É possível indicar a célula que iniciará em receber os valores da lista, pela referência ou posição da linha e coluna, mas caso oculte a referência da célula, os valores iniciarão pela célula "A1".

No FillObject pode indicar se um cabeçalho será ou não gerado automaticamente, passando o parâmetro 'generateHeader' com valor true ou false. Caso verdadeiro, o nome da propriedade do objeto será o nome mostrado no cabeçalho. Ainda não há suporte ao atributo "Display" para obter o nome do cabeçalho, indique aqui se há interesse nisso. E veja em Globalização como fazer traduções automáticas dos cabeçalhos de acordo com um idioma.

Exemplo de preenchimento de lista de objetos iniciando na célula B2:

    public class TestModel
    {
        public TestModel(string name, double number, DateTime objDate, TimeSpan time)
        {
            Name = name;
            Number = number;
            ObjDate = objDate;
            Time = time;            
        }

        public string Name { get; set; }
        public double Number { get; set; }
        public DateTime ObjDate { get; set; }
        public TimeSpan Time { get; set; }
    }

    List<TestModel> list = new();
    list.Add(new("Line 1", 10, DateTime.Today, TimeSpan.FromHours(3)));
    list.Add(new("Line 2", -10, DateTime.Now, TimeSpan.FromMinutes(12)));
    list.Add(new("Line 3", 10.6d, DateTime.UtcNow, TimeSpan.FromMinutes(45).Add(TimeSpan.FromSeconds(31))));

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")
                   .FillObject(list, 2, 2)

Criação de Tabelas

Dentro de uma folha de planilha, é possível adicionar tabelas, utilize o método "AddTable", passando o nome da tabela e a referência da célula que iniciará a tabela, passando o valor da referência em string ou posição da linha e coluna, mas caso oculte a referência da célula, a tabela iniciará pela célula "A1".

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")
                   .AddTable("My Table", "B2")

Ao adicionar uma tabela, o Builder irá mudar para que todas as chamadas a seguir sejam criadas dentro dessa tabela, mas você pode voltar o Builder para a folha de planilha quando desejar chamando o método "Sheet" ou voltar diretamente para a planilha usando o método "Spreadsheet":

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")
                   .AddTable("My Table")
                   .Sheet()
                   .AddTable("My Table 2", "Z2")

Preenchendo Tabela com Matrizes Bidimensionais

Dentro da tabela, é possível preencher ela usando o método "Fill", passando uma matriz bidimensionais, seu uso é semelhante que ocorre diretamente na Folha da Planilha, porém, não é necessário passar a referência da célula, uma vez que a tabela já tem essa posição:

    var list = new List<List<object>>();

    list.Add(new List<object>() { "Line 1", 10, DateTime.Today, TimeSpan.FromHours(3) });
    list.Add(new List<object>() { "Line 2", -10, DateTime.Now, TimeSpan.FromMinutes(12) });
    list.Add(new List<object>() { "Line 3", 10.6m, DateTime.UtcNow, TimeSpan.FromMinutes(45).Add(TimeSpan.FromSeconds(31)) });

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")
                   .AddTable("My Table")
                   .Fill(list)

Preenchendo Lista de Objetos

Dentro da tabela, é possível preencher ela com uma lista de objetos usando o método "FillObject", seu uso é semelhante que ocorre diretamente na Folha da Planilha, porém, não é necessário passar a referência da célula, uma vez que a tabela já tem essa posição:

    public class TestModel
    {
        public TestModel(string name, double number, DateTime objDate, TimeSpan time)
        {
            Name = name;
            Number = number;
            ObjDate = objDate;
            Time = time;            
        }

        public string Name { get; set; }
        public double Number { get; set; }
        public DateTime ObjDate { get; set; }
        public TimeSpan Time { get; set; }
    }

    List<TestModel> list = new();
    list.Add(new("Line 1", 10, DateTime.Today, TimeSpan.FromHours(3)));
    list.Add(new("Line 2", -10, DateTime.Now, TimeSpan.FromMinutes(12)));
    list.Add(new("Line 3", 10.6d, DateTime.UtcNow, TimeSpan.FromMinutes(45).Add(TimeSpan.FromSeconds(31))));

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")
                   .AddTable("My Table")
                   .FillObject(list)

Personalizando Cabeçalhos

É possível adicionar cabeçalhos da tabela, quando é preenchido com matriz bidimensionais ou ignorando a geração de cabeçalho de preenchimento com lista de objetos, usando o método "AddHeader" e passando uma lista de strings

    List<string> headers = new()
    {
        "Column 1",
        "Column 2",
        "Column 3",
        "Column 4"
    };

    ReportGenerator.Spreadsheet()
                   .AddSheet("Sheet 1")
                   .AddTable("My Table")
                   .Fill(list)
                   .AddHeader(headers )

Globalização

Alguns dados gerados, podem ser diferente para cada país, atualmente apenas a geração de cabeçalhos de lista de objetos utiliza a globalização. É necessário passar dois parâmetros, ResourceManager com as strings para tradução e a CultureInfo atual que deseja utilizar. No builder da Planilha passe os atributos necessários:

    ReportGenerator.Spreadsheet()
                   .SetResourceManager(Texts.ResourceManager)
                   .SetCultureInfo(new CultureInfo("pt"))

Caso haja mais itens que precise passar pelo processo de globalização, nos informe aqui.

Formatação de Campos

Não há suporte para formatação dos campos, indique aqui se há interesse nisso.

Adição de Estilos

Não há suporte para personalização de estilos, indique aqui se há interesse nisso.

Geração do Relatório

Atualmente é possível gerar relatório de três formas diferente, salvando em arquivo, array de bytes e Stream.

Salvando em Arquivos

    ReportGenerator.Spreadsheet()
                   ...
                   .BuildAsync(@"test.xlsx");
    

Salvando em Stream

    MemoryStream ms = new();
    ReportGenerator.Spreadsheet()
                   ...
                   .BuildAsync(ms);

Array de Bytes

    byte[] buffer = await ReportGenerator.Spreadsheet()
                            ...
                            .BuildAsync();

Técnicas Avançadas

Usando o desenvolvimento Fluent Interface é possível criar alguns cenários avançados, vamos explorar um caso de uso.

Builders

A forma simples e recomendada para estender a API no seu código é utilizando métodos de extensão, a seguir seguem as classes que pode utilizar para estender e facilitar o desenvolvimento de relatórios dentro do seu próprio projeto, todos no namespace: BlackDigital.Report.Spreadsheet

Classe Descrição
SpreadsheetBuilder Builder no nível do arquivo da planilha
SheetBuilder Builder no nível de folha de planilha
TableBuilder Builder no nível de tabelas

Padronização de Folhas de Planilhas

Para criar um padrão de exportação dentro do seu projeto, nesse cenário, esse template consiste em ter no topo da planilha o nome da empresa, data e hora de geração nome da tabela, depois a tabela com os dados.

Criando o método de extensão para esse cenário:

    public static class ReportExtension
    {
        public static SpreadsheetBuilder MyReport<TModel>(this SpreadsheetBuilder builder, 
                                                          string name, 
                                                          IEnumerable<TModel> list)
        {
            return builder.SetCompany("My Company")
                          .AddSheet(name)
                          .AddValue("My Company")
                          .AddValue("Date: ", "A2")
                          .AddValue(DateTime.Now, "B2")
                          .AddValue(name, "A3")
                          .AddTable("report", "A5")
                          .FillObject(list)
                          .Spreadsheet();
        }
    }

E para chamar esse método no meio do seu código:

    ReportGenerator.Spreadsheet()
               .MyReport("My report", list)

Padronização de Builder

Outro cenário possível é a geração de relatório em uma pasta temporária para download

        public static async Task<string> BuilderReportAsync(this SpreadsheetBuilder builder)
        {
            string filename = Guid.NewGuid().ToString();
            filename = filename.Replace("-", "");
            filename = $"{filename}.xlsx";

            await builder.BuildAsync($"/var/www/downloads/reports/{filename}");

            return filename;
        }

Exemplo de uso:

string filename = await ReportGenerator.Spreadsheet()
                                       .MyReport("My report", list)
                                       .BuilderReportAsync();