1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

  2. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

Dica Avançada: Exportação Ultra-Rápida para Excel

Discussão em 'Progress 4GL' iniciado por rafael.andrade, Março 31, 2014.

?

O que você achou dessa dica?

  1. Excelente

    8 voto(s)
    66.7%
  2. Muito boa

    4 voto(s)
    33.3%
  3. "Nem fede, nem cheira" rsrsrsrs

    0 voto(s)
    0.0%
  1. rafael.andrade

    rafael.andrade Membro Master Moderador Equipe de Suporte

    Boa tarde a todos!

    Bom a mágica é muito mais fácil do que parece.

    Conhecimento:
    ========================================================
    Existe um recurso no Excel chamado "Text to Column", onde ele converte um carácter específico em quebra de linha, exemplo:
    Dentro da célula A1 contém o texto: "AAA¶BBB¶CCC"
    Ao aplicar esse recurso alterando o caracter ¶ em quebra de coluna, fica assim:
    A1 = "AAA"
    B1 = "BBB"
    C1 = "CCC"

    Então, aí que está o segredo: Ao invés de fazer o Assign no A1, B1, C1, D1,... você faz somente nas linhas: A1, A2, A3, A4, A5 e depois aplica o recurso de quebra de coluna e pronto, a planilha inteira é preenchida somente fazendo carga na linha.

    Cheguei a perceber melhoria de 10x na performance dependendo da quantidade de registros e principalmente de colunas.
    ========================================================

    Aplicando o Conhecimento:
    ========================================================
    1º) Criar uma tabela temporária. (Pode ser LIKE alguma tabela ou definindo os FIELDS separadamente):
    DEFINE TEMP-TABLE ttExcel
    FIELD nome AS CHARACTER
    FIELD idade AS INTEGER.

    2º) Criar um BUFFER dessa tabela temporária:
    DEFINE BUFFER ttExcel2 FOR ttExcel.

    3º) Definir as colunas padrão Excel (Como tive preguiça, fiz até a coluna GZ, que já acho muito)
    DEF VAR ColunasExcel AS CHAR EXTENT INIT ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U",
    "V","W","X","Y","Z","AA","AB","AC","AD","AE","AF","AG","AH","AI","AJ","AK","AL","AM",
    "AN","AO","AP","AQ","AR","AS","AT","AU","AV","AW","AX","AY","AZ","BA","BB","BC","BD",
    "BE","BF","BG","BH","BI","BJ","BK","BL","BM","BN","BO","BP","BQ","BR","BS","BT","BU",
    "BV","BW","BX","BY","BZ","CA","CB","CC","CD","CE","CF","CG","CH","CI","CJ","CK","CL",
    "CM","CN","CO","CP","CQ","CR","CS","CT","CU","CV","CW","CX","CY","CZ","DA","DB","DC",
    "DD","DE","DF","DG","DH","DI","DJ","DK","DL","DM","DN","DO","DP","DQ","DR","DS","DT",
    "DU","DV","DW","DX","DY","DZ","EA","EB","EC","ED","EE","EF","EG","EH","EI","EJ","EK",
    "EL","EM","EN","EO","EP","EQ","ER","ES","ET","EU","EV","EW","EX","EY","EZ","FA","FB",
    "FC","FD","FE","FF","FG","FH","FI","FJ","FK","FL","FM","FN","FO","FP","FQ","FR","FS",
    "FT","FU","FV","FW","FX","FY","FZ","GA","GB","GC","GD","GE","GF","GG","GH","GI","GJ",
    "GK","GL","GM","GN","GO","GP","GQ","GR","GS","GT","GU","GV","GW","GX","GY","GZ"].

    4º) Fazer a carga da tabela temporária.

    5º) Criar uma procedure GeraExcel (ou outro nome) e coloque a inicialização do Excel:
    CREATE "Excel.Application" chExcel. /*criar planilha*/
    chWorkbook = chExcel:Workbooks:ADD(). /* Cria novo documento do Excel com 1 planilha*/
    chExcel:VISIBLE = FALSE. /* Impede a Interação do usuário */
    chWorkbook:Worksheets(1):Activate.
    chWorksheet = chWorkbook:Worksheets(1).

    /* Desliga a verificação de Erros de formato de Fórmulas */
    chExcel:ErrorCheckingOptions:BackgroundChecking = FALSE.
    ASSIGN txtProgressso :SCREEN-VALUE IN FRAME F-Aguarde = "Configurando Planilha Excel...".

    PROCESS EVENTS.

    6º) Hora da mágia...:
    DEF VAR xi AS INTEGER INIT 0.
    DEF VAR ValColuna AS CHAR INIT "".
    DEF VAR colAtual AS INTEGER INIT 0.
    DEF VAR NumColunas AS INTEGER.
    DEF VAR NumLinhas AS INTEGER.
    DEF VAR Origem AS CHAR.
    DEF VAR Destino AS CHAR.
    DEF VAR ValorAtual AS CHAR.

    FOR EACH ttExcel2 NO-LOCK.
    PROCESS EVENTS.
    ASSIGN xi = xi + 1.
    DO colAtual = 1 TO BUFFER ttExcel2 :NUM-FIELDS.
    PROCESS EVENTS.
    IF BUFFER ttExcel2:BUFFER-FIELD(colAtual) :DATA-TYPE = "CHARACTER" THEN DO:
    ASSIGN ValorAtual = "''" + BUFFER ttExcel2:BUFFER-FIELD(colAtual) :BUFFER-VALUE NO-ERROR.
    END.
    ELSE DO:
    ASSIGN ValorAtual = BUFFER ttExcel2:BUFFER-FIELD(colAtual) :BUFFER-VALUE NO-ERROR.
    END.
    IF colAtual = 1 THEN DO:
    ASSIGN ValColuna = (IF ValorAtual = ? OR ValorAtual = "" THEN "(vazio)" ELSE ValorAtual).
    END.
    ELSE DO:
    ASSIGN ValColuna = ValColuna + "¶" + (IF ValorAtual = ? OR ValorAtual = "" THEN "(vazio)" ELSE ValorAtual).
    END.
    END.
    chWorksheet:range("A" + STRING(xi + 1)):VALUE = ValColuna NO-ERROR.
    ASSIGN txtProgressso :SCREEN-VALUE IN FRAME F-Aguarde = "Gravando linha: " + STRING(xi).
    END.

    /* Converte o separador "¶" em quebra de coluna */
    IF xi > 0 THEN DO:
    chWorksheet:range("A2:A" + STRING(NumLinhas + 1)):TextToColumns(,1,1,FALSE,FALSE,FALSE,FALSE,FALSE,TRUE,"¶",,,,TRUE).
    END.
    chWorksheet:Range("A:ZZ"):REPLACE("''","'").

    7º) Finaliza o Arquivo e exibe na tela:
    chExcel:VISIBLE = TRUE.

    RELEASE OBJECT chExcel NO-ERROR.
    RELEASE OBJECT chWorkbook NO-ERROR.
    RELEASE OBJECT chWorksheet NO-ERROR.
    RELEASE OBJECT chWorksheet2 NO-ERROR.
    ========================================================

    Considerações Finais:
    ========================================================
    1. O Caracter usado para quebra de linha é o padrão do Word simplemente porque ninguém digite isso no sistema: ¶
    2. Quando o valor do campo é STRING eu adiciono duas apas simples antes do valor para não gerar problema na quebra de linha, para outros casos como números não faço isso.
    3. Campos vazios precisam ser preenchidos com alguma coisa, no caso usei "(vazio)" porque todos as linhas selecionadas automaticamente precisam ter a mesma quantidade de colunas.
    ========================================================

    Grato pela atenção.

    Sou autor desta dica, favor, se for replicar a dica em outro lugar mencione o Autor.

    Autor: Rafael Andrade
    Empresa: Vector7 Ltda (www.vector7.inf.br)


    IMPORTANTE
    ===========================================

    - Não esqueçam de votar na enquete, blz? Vlw
    ===========================================
    Última edição: Abril 9, 2014
  2. clandestinos

    clandestinos Sem Pontuação

    Oi Rafael,

    dá pra usar esse esquema utilizando um modelo excel?

    Att,

    Adriano Ferreira
  3. jaozi_nho

    jaozi_nho Membro Participativo

    Eu utilizo o QueryTables, mandando todos os dados para um arquivo .txt ou .csv e linkando com queryTables, é muito rápido e talvez até mais pratico, fica como dica tambem .

    Abraço .
  4. clandestinos

    clandestinos Sem Pontuação

    Me desculpe, não conheço esse método, utilizo modelo, porque a planilha é um pouco complexa, conta com tabelas dinâmicas...
    Se você puder me mostrar um exemplo de uso do QueryTables.
  5. Japs

    Japs Sem Pontuação

    João, pode nos dar mais detalhes de como usar esse seu método?

    Obrigado!
  6. jaozi_nho

    jaozi_nho Membro Participativo

    Basicamente ele faz a mesma coisa de ir na opção Dados -> De Texto

    fArquivo é um arquivo .csv, que foi criado usando o comando EXPORT DELIMITER ';'

    Código:
    /*Configurando Excel*/
    RUN pi-acompanhar IN h-acomp("Configurando Excel...") .
    
    DEF VAR chExcel             AS COM-HANDLE NO-UNDO .
    DEF VAR chSheet             AS COM-HANDLE NO-UNDO .
    DEF VAR chQueryTable        AS COM-HANDLE NO-UNDO .
    
    CREATE "Excel.Application" chExcel.
    chExcel:VISIBLE = YES .
    chSheet = chExcel:Workbooks:ADD .
    
    /*Cotacoes*/
    chSheet = chExcel:Sheets:ITEM(1) .
    chSheet:NAME = "Taxas.
    chSheet:QueryTables:ADD("TEXT;" + fCotacoes , chSheet:cells(1 , 1)) .
    chQueryTable = chSheet:QueryTables(1) .
    RUN pi-link-excel .
    chSheet:COLUMNS("A:B"):EntireColumn:AutoFit .
    
    PROCEDURE pi-link-excel:
        ASSIGN
            chQueryTable:FieldNames = TRUE
            chQueryTable:RowNumbers = FALSE
            chQueryTable:FillAdjacentFormulas = FALSE
            chQueryTable:PreserveFormatting = TRUE
            chQueryTable:RefreshOnFileOpen = FALSE
            chQueryTable:RefreshStyle = 1
            chQueryTable:SavePassword = FALSE
            chQueryTable:SaveData = TRUE
            chQueryTable:AdjustColumnWidth = FALSE
            chQueryTable:RefreshPeriod = 0
            chQueryTable:TextFilePromptOnRefresh = FALSE
            chQueryTable:TextFilePlatform = 437
            chQueryTable:TextFileStartRow = 1
            chQueryTable:TextFileParseType = 1
            chQueryTable:TextFileTextQualifier = 2
            chQueryTable:TextFileConsecutiveDelimiter = FALSE
            chQueryTable:TextFileTabDelimiter = FALSE
            chQueryTable:TextFileSemicolonDelimiter = TRUE
            chQueryTable:TextFileCommaDelimiter = FALSE
            chQueryTable:TextFileSpaceDelimiter = FALSE
            chQueryTable:TextFileTrailingMinusNumbers = TRUE
            /*chQueryTable:TextFileColumnDataTypes = iTypes*/
            .
        chQueryTable:REFRESH .
        ASSIGN chQueryTable:BackgroundQuery = FALSE.
    END PROCEDURE.
    
    rafael.andrade curtiu isso.

Compartilhe esta Página