quinta-feira, 17 de abril de 2025

Como Exportar Dados do Trello para Excel em Português (PT-BR)

Tenho utilizado o Trello para organizar as tarefas do meu trabalho, mas precisei exportar os dados para o Excel, e percebi que não havia uma opção nativa para isso. Após uma pesquisa, encontrei um script VBA desenvolvido por Kevin Harper, que estava disponível na internet. O script é totalmente funcional, mas não fazia a conversão adequada para o português (PT-BR).

Diante disso, decidi atualizar o código mantendo os direitos autorais de Kevin Harper e realizar as devidas adaptações para que ele funcione corretamente em português. Agora, o script está pronto para ser utilizado e pode ajudar a facilitar o processo de exportação de dados do Trello para o Excel, respeitando o idioma português.

Abaixo, compartilho o script atualizado para que vocês possam utilizar e aprimorar ainda mais a organização das suas tarefas.





'    Tool for importing Trello JSON files into Excel.
'    Written by Kevin Harper, 16-Mar-17.
'    Updated by Joaquim GVF, 17-Apr-25
'
'    This spreadsheet uses the JSON export from Trello to import a rich content into Excel as a list of cards or a list of actions.
'    No Chrome or other browser extensions are required for the export/import.
'    The import scripts use the JSON parser capability developed by Tim Hall, available at:
'    https://github.com/VBA-tools/VBA-JSON
'    The VBA-JSON parser is already included in the spreadsheet file
'
'    From within the spreadsheet, there are two import options
'    1. The "ImportedCards" sheet runs vbscript ImportMyTrello - this creates a list of all the cards on your Trello board,
'    excluding those that have been archived.
'    2. The "ImportedActions" sheet runs vbscript ImportActionsFromTrello - this creates a list of
'    all the actions that have been carried out on your Trello board -
'    by applying Excel filters, you can create a list of specific actions;  eg, such as a record of who and when moved cards into a particular column.
'
'    To export a board from Trello into Excel using the spreadsheet, carry out the following steps:
'
'    (1) In Trello, for your chosen board and using the right-hand side menu options, select:
'           More / Print and Export / Export to JSON
'
'    o  In Chrome, this will display the JSON code in the open tab.  Save this as a local file on your computer,
'    by right clicking and selecting "Save as..."
'    o  In Internet Explorer, this will download the JSON export as a local file on your computer.
'
'    (2) Using the spreadsheet, click the "Import" button on either worksheet and select your downloaded JSON file
'    ....and the import should proceed.
'
' Copyright (c) 2017, 2018, Kevin Harper
'
'   version 1.0, 16-Mar-17 - first version published in GitHub
'   version 1.1, 17-May-18 - added error handling for lookup of idMemberAdded and idMember where the added person is no
'   longer a member of the board and therefore not found in the array of Members.
'   version 1.2, 17-Apr-25 - updated by Joaquim GVF to add support for import in Portuguese (PT-BR) language with UTF-8.
'
' All rights reserved.
'
' Redistribution and use in source and binary forms, with or without
' modification, are permitted provided that the following conditions are met:
'     * Redistributions of source code must retain the above copyright
'       notice, this list of conditions and the following disclaimer.
'     * Redistributions in binary form must reproduce the above copyright
'       notice, this list of conditions and the following disclaimer in the
'       documentation and/or other materials provided with the distribution.
'     * Neither the name of the  nor the
'       names of its contributors may be used to endorse or promote products
'       derived from this software without specific prior written permission.
'
' THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
' ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
' WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
' DISCLAIMED. IN NO EVENT SHALL  BE LIABLE FOR ANY
' DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
' (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
' LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
' ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
' (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
' SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Option Explicit
Public myFile As String
Public cardMovedColumn As Boolean

Public Sub ImportMyTrello()

    Dim JsonText As String
    Dim Parsed As New Dictionary
    
    Const StartRow = 4    'Row to contain column headers, should be greater than 3
    
    ' Fetch the JSON string and then parse it to Dictionary, or Exit if file selection is cancelled:
    JsonText = GetJsonText()
    If JsonText = "" Then Exit Sub
    
    Set Parsed = JsonConverter.ParseJson(JsonText)
    
'    Clear the current content from the spreadsheet:
'    Sheets("ImportedCards").Cells.ClearContents
    Range(Sheets("ImportedCards").Cells(1, 1), Sheets("ImportedCards").Cells(1, 1).SpecialCells(xlLastCell)).ClearContents

'    and insert the Board name and URL
    Sheets("ImportedCards").Cells(1, 3) = Parsed("name")
    Sheets("ImportedCards").Cells(2, 1) = "URL for imported Trello board:"
    Sheets("ImportedCards").Hyperlinks.Add Anchor:=Cells(3, 1), Address:=Parsed("url"), TextToDisplay:=Parsed("url")
        
'   =======================================================================================

'    Create an array called Columns, of content (id, name);  this is used later to lookup
'    column names based on their id

    Dim Columns As Variant
    Dim NumberOfColumns As Integer
    Dim NumberOfArchivedColumns As Integer
    Call FetchColumns(Parsed, Columns, NumberOfColumns, NumberOfArchivedColumns)

'   =======================================================================================

'    Create an array called Members, of content (id, fullName);  this is used later to lookup
'    people's names based on their id

    Dim Members As Variant
    Dim NumberOfMembers As Integer
    Call FetchMembers(Parsed, Members, NumberOfMembers)

'   =======================================================================================
    
'    Create an array called Cards, of content aligned to the following headers:
   
    Const CollectedColumns = 10
    Dim LastColumnIndex As Integer
    LastColumnIndex = CollectedColumns - 1
    Dim Header(CollectedColumns) As String
    Header(0) = "Column"
    Header(1) = "Card title"
    Header(2) = "Description"
    Header(3) = "Date of last update"
    Header(4) = "Due date"
    Header(5) = "Card Members"
    Header(6) = "Labels"
    Header(7) = "Card ID"
    Header(8) = "Attachments"
    Header(9) = "URL"

    Dim myObject As String
    myObject = "cards"
    
    Dim Card As Dictionary
    Dim Label As Dictionary
    Dim CardMember As Variant
    Dim Cards As Variant
    Dim Filename As Variant
    Dim NumberOfCards As Integer
    Dim NumberOfArchivedCards As Integer
    Dim i As Integer
    Dim FirstPass As Boolean

    
'    Redim the upper array bounds, where lowest bounds are 0
    ReDim Cards(Parsed(myObject).Count - 1, LastColumnIndex)
    
'   Loop through each card in the list, skipping it if it has been closed in Trello (ie archived):
    i = 0
    For Each Card In Parsed(myObject)
        If (Card("closed") <> "True") Then
            
'           First do all the card fields that are single values:
            Cards(i, 0) = Application.VLookup(Card("idList"), Columns, 2, False)        ' Lookup the list id to extract it's name, stored in the list created earlier
            Cards(i, 1) = Card("name")
            Cards(i, 2) = Card("desc")
            Cards(i, 3) = Left(Card("dateLastActivity"), 10)
            Cards(i, 4) = Left(Card("due"), 10)
            Cards(i, 7) = Card("idShort")
            Cards(i, 9) = Card("shortUrl")
            
'           The next three fields may have more than one value for the card; where multiple values exist, a comma separated list is created
            FirstPass = True
            For Each CardMember In Card("idMembers")
     
                If FirstPass Then
                    Cards(i, 5) = Application.VLookup(CardMember, Members, 2, False)    ' Lookup the person's id to extract their name, stored in the list created earlier
                    FirstPass = False
                Else
                    Cards(i, 5) = Cards(i, 5) & ", " & Application.VLookup(CardMember, Members, 2, False)
                End If
            Next CardMember
           
            FirstPass = True
            For Each Label In Card("labels")
                If FirstPass Then
                    Cards(i, 6) = Label("name")
                    FirstPass = False
                Else
                    Cards(i, 6) = Cards(i, 6) & ", " & Label("name")
                End If
            Next Label
    
            FirstPass = True
            For Each Filename In Card("attachments")
                If FirstPass Then
                    Cards(i, 8) = Filename("name")
                    FirstPass = False
                Else
                    Cards(i, 8) = Cards(i, 8) & ", " & Filename("name")
                End If
            Next Filename
                      
            i = i + 1
        Else
            NumberOfArchivedCards = NumberOfArchivedCards + 1
            
        End If
    Next Card
    
    NumberOfCards = i
'   =======================================================================================

'    Put the Cards array into the spreadsheet:
    Sheets("ImportedCards").Range(Cells(StartRow, 1), Cells(StartRow, CollectedColumns)) = Header
    Sheets("ImportedCards").Range(Cells(StartRow + 1, 1), Cells(StartRow + 1 + NumberOfCards - 1, CollectedColumns)) = Cards
    
'   Add some stats in the header:
    
    Sheets("ImportedCards").Cells(2, 4) = NumberOfColumns
    Sheets("ImportedCards").Cells(2, 5) = "columns (lists) imported from Trello"
    Sheets("ImportedCards").Cells(3, 4) = NumberOfCards
    Sheets("ImportedCards").Cells(3, 5) = "cards"
    
    Sheets("ImportedCards").Cells(2, 7) = NumberOfArchivedColumns
    Sheets("ImportedCards").Cells(2, 8) = "archived column(s) NOT imported"
    Sheets("ImportedCards").Cells(3, 7) = NumberOfArchivedCards
    Sheets("ImportedCards").Cells(3, 8) = "archived card(s) NOT imported"
    
    Call FormatSheet("ImportedCards", StartRow)

End Sub

Public Sub ImportActionsFromTrello()

    Dim JsonText As String
    Dim Parsed As New Dictionary

    Const StartRow = 4    'Row to contain column headers, should be greater than 3
    
    ' Fetch the JSON string and then parse it to Dictionary, or Exit if file selection is cancelled:
    JsonText = GetJsonText()
    If JsonText = "" Then Exit Sub
    
    Set Parsed = JsonConverter.ParseJson(JsonText)
    
    
'    Clear the current content from the spreadsheet:
'    Sheets("ImportedActions").Cells.ClearContents
    Range(Sheets("ImportedActions").Cells(1, 1), Sheets("ImportedActions").Cells(1, 1).SpecialCells(xlLastCell)).ClearContents
    
'    and insert the Board name and URL
    Sheets("ImportedActions").Cells(1, 3) = Parsed("name")
    Sheets("ImportedActions").Cells(2, 1) = "URL for imported Trello board:"
    Sheets("ImportedActions").Hyperlinks.Add Anchor:=Cells(3, 1), Address:=Parsed("url"), TextToDisplay:=Parsed("url")
        
'   =======================================================================================

'    Create an array called Members, of content (id, fullName);  this is used later to lookup
'    people's names based on their id

    Dim Members As Variant
    Dim NumberOfMembers As Integer
    Call FetchMembers(Parsed, Members, NumberOfMembers)
    
'   =======================================================================================
    
'    Create an array called Cards, of content aligned to the following headers:

    Const CollectedColumns = 6
    Dim LastColumnIndex As Integer
    LastColumnIndex = CollectedColumns - 1
    Dim Header(CollectedColumns) As String
    Header(0) = "Column"
    Header(1) = "Card title"
    Header(2) = "Member"
    Header(3) = "Action"
    Header(4) = "Date"
    Header(5) = "Details"
    
    Dim myObject As String
    myObject = "actions"
    Dim Action As Dictionary
    Dim Card As Variant
    Dim Actions As Variant
    Dim NumberOfActions As Integer
    Dim i As Integer
    Dim FirstPass As Boolean
    Dim lookup As Variant
    
'    Redim the upper array bounds, where lowest bounds are 0
    ReDim Actions(Parsed(myObject).Count - 1, LastColumnIndex)
    
'   Loop through each card in the list, skipping it if it has been closed in Trello (ie archived):
    i = 0
    For Each Action In Parsed(myObject)
            
            Actions(i, 0) = FindActionListName(Action)
            Actions(i, 1) = FindActionCardName(Action)

            Actions(i, 2) = Application.VLookup(Action("idMemberCreator"), Members, 2, False)        ' Lookup the person's id to extract their name, stored in the list created earlier
            Actions(i, 3) = Action("type")
            Actions(i, 4) = Left(Action("date"), 10)
            
            If Action("type") = "addAttachmentToCard" Then
                Actions(i, 5) = "Attached file: " & Action("data")("attachment")("name")
                
            ElseIf Action("type") = "deleteAttachmentFromCard" Then
                Actions(i, 5) = "Removed file: " & Action("data")("attachment")("name")
'                Actions(i, 0) =
                
            ElseIf Action("type") = "commentCard" Then
                Actions(i, 5) = "Added comment: " & Action("data")("text")
                
            ElseIf Action("type") = "createCard" Then
                Actions(i, 5) = "New card added"
                
            ElseIf Action("type") = "copyCard" Then
                Actions(i, 5) = "Copied from: " & Action("data")("cardSource")("name")
                
            ElseIf Action("type") = "addChecklistToCard" Then
                Actions(i, 5) = "Added checklist: " & Action("data")("checklist")("name")
                
            ElseIf Action("type") = "removeChecklistFromCard" Then
                Actions(i, 5) = "Removed checklist: " & Action("data")("checklist")("name")
                
            ElseIf Action("type") = "updateChecklist" Then
                Actions(i, 5) = "Changed from [" & Action("data")("old")("name") _
                    & "] to [" & Action("data")("checklist")("name") & "]"
                    
            ElseIf Action("type") = "updateCheckItemStateOnCard" Then
                Actions(i, 5) = "Checklist item [" & Action("data")("checkItem")("name") & "] set to <" & _
                    Action("data")("checkItem")("state") & ">"
                
            ElseIf Action("type") = "createList" Then
                Actions(i, 5) = "Added new column: " & Action("data")("list")("name")
                
            ElseIf Action("type") = "updateList" Then
                If Action("data")("old")("name") <> "" Then
                    Actions(i, 5) = "Column changed from: " & Action("data")("old")("name")
                    
                ElseIf Action("data")("old")("pos") > Action("data")("list")("pos") Then
                    Actions(i, 5) = "Column moved left"
                    
                ElseIf Action("data")("old")("pos") < Action("data")("list")("pos") Then
                    Actions(i, 5) = "Column moved right"
                    
                End If
                
            ElseIf Action("type") = "createBoard" Then
                Actions(i, 5) = "Added new board: " & Action("data")("board")("name")
                
            ElseIf Action("type") = "updateBoard" Then
                Actions(i, 5) = "Background changed from [" & Action("data")("old")("prefs")("background") _
                    & "] to [" & Action("data")("board")("prefs")("background") & "]"
                
            ElseIf Action("type") = "updateCard" Then
                If Action("data")("old")("due") <> "" Then
                    Actions(i, 5) = "Due changed from: " & Left(Action("data")("old")("due"), 10)
                    
                ElseIf Action("data")("old")("name") <> "" Then
                    Actions(i, 5) = "Name changed from: " & Action("data")("old")("name")
                    
                ElseIf Action("data")("old")("pos") > Action("data")("card")("pos") Then
                    Actions(i, 5) = "Card moved up in column"
                    
                ElseIf Action("data")("old")("pos") < Action("data")("card")("pos") Then
                    Actions(i, 5) = "Card moved down in column"
                    
                ElseIf cardMovedColumn Then
                    Actions(i, 5) = "Moved from column: " & Action("data")("listBefore")("name")
                    
                ElseIf Len(Action("data")("old")("desc")) > 0 Then
                    Actions(i, 5) = "Card description amended"
                    
                ElseIf Action("data")("old")("desc") = "" Then
                    Actions(i, 5) = "Card description added"
                    
                End If

            ElseIf Action("type") = "addMemberToBoard" Then
'                Actions(i, 5) = "Added new member: " & Application.VLookup(Action("data")("idMemberAdded"), Members, 2, False)
'               [10-May-18]replaced with, handles error if
                lookup = Application.VLookup(Action("data")("idMemberAdded"), Members, 2, False)
                If Not IsError(lookup) Then
                    Actions(i, 5) = "Added new member: " & lookup
                Else
                    Actions(i, 5) = "Added new member: ERROR: " & Action("data")("idMemberAdded") & " not found"
                End If

                          
            ElseIf Action("type") = "addMemberToCard" Then
'                Actions(i, 5) = "Added to card: " & Application.VLookup(Action("data")("idMember"), Members, 2, False)
'               [10-May-18]replaced with
                lookup = Application.VLookup(Action("data")("idMember"), Members, 2, False)
                If Not IsError(lookup) Then
                    Actions(i, 5) = "Added to card: " & lookup
                Else
                    Actions(i, 5) = "Added to card: ERROR: " & Action("data")("idMember") & " not found"
                End If
                
            ElseIf Action("type") = "removeMemberFromCard" Then
'                Actions(i, 5) = "Removed: " & Application.VLookup(Action("data")("idMember"), Members, 2, False)
'               [10-May-18]replaced with
                lookup = Application.VLookup(Action("data")("idMember"), Members, 2, False)
                If Not IsError(lookup) Then
                    Actions(i, 5) = "Removed: " & lookup
                Else
                    Actions(i, 5) = "Removed: ERROR: " & Action("data")("idMember") & " not found"
                End If
                
            ElseIf Action("type") = "addToOrganizationBoard" Then
                Actions(i, 5) = "Added to org: " & Action("data")("organization")("name")
                               
        End If
       
        i = i + 1
        
    Next Action
    
    NumberOfActions = i
'   =======================================================================================

'    Put the Cards array into the spreadsheet:
    Sheets("ImportedActions").Range(Cells(StartRow, 1), Cells(StartRow, CollectedColumns)) = Header
    Sheets("ImportedActions").Range(Cells(StartRow + 1, 1), Cells(StartRow + 1 + NumberOfActions - 1, CollectedColumns)) = Actions
    
'   Add some stats in the header:
    
    Sheets("ImportedActions").Cells(3, 4) = NumberOfActions
    Sheets("ImportedActions").Cells(3, 5) = "actions"

    Call FormatSheet("ImportedActions", StartRow)

End Sub


Private Function GetJsonText_old()
'   Open the filechooser, select file and read .json file
    Dim FSO As New FileSystemObject
    Dim JsonTS As TextStream
    
    myFile = Application.GetOpenFilename("JSON Files (*.json),*.json", 1, "Open JSON file for import")
    If myFile <> "False" Then
        Set JsonTS = FSO.OpenTextFile(myFile, ForReading)
        GetJsonText = JsonTS.ReadAll
        JsonTS.Close
    Else
        GetJsonText = ""
    End If
    
End Function


Function GetJsonText() As String
    Dim fileDialog As fileDialog
    Dim filePath As String
    Dim fileStream As Object
    Dim inputStream As Object

    Set fileDialog = Application.fileDialog(msoFileDialogFilePicker)
    
    With fileDialog
        .AllowMultiSelect = False
        .Title = "Selecione o arquivo JSON exportado do Trello"
        .Filters.Clear
        .Filters.Add "Arquivos JSON", "*.json"
        
        If .Show <> -1 Then
            GetJsonText = ""
            Exit Function
        End If
        
        filePath = .SelectedItems(1)
    End With

    ' Criar objetos para leitura com codificação UTF-8
    Set inputStream = CreateObject("ADODB.Stream")
    inputStream.Charset = "utf-8"
    inputStream.Open
    inputStream.LoadFromFile filePath
    GetJsonText = inputStream.ReadText
    inputStream.Close
    Set inputStream = Nothing
End Function


Private Sub FetchColumns(Parsed As Dictionary, Columns As Variant, NumberOfColumns As Integer, NumberOfArchivedColumns As Integer)

    Dim Column As Dictionary
    Dim myObject As String
    Dim i As Integer
    myObject = "lists"
'    Dim Columns As Variant
'    Dim NumberOfColumns As Integer
'    Dim NumberOfArchivedColumns As Integer
'    Redim the upper array bounds, where lowest bounds are 0
    ReDim Columns(Parsed(myObject).Count - 1, 1)
    
    i = 0
    For Each Column In Parsed(myObject)
        If (Column("closed") <> "True") Then
            Columns(i, 0) = Column("id")
            Columns(i, 1) = Column("name")
    
            i = i + 1
        Else
            NumberOfArchivedColumns = NumberOfArchivedColumns + 1
        End If
    Next Column
    NumberOfColumns = i

End Sub

Private Sub FetchMembers(Parsed As Dictionary, Members As Variant, NumberOfMembers As Integer)


    Dim Member As Dictionary
    Dim myObject As String
    Dim i As Integer
    myObject = "members"
    
'    Dim Members As Variant
'    Dim NumberOfMembers As Integer
'    Redim the upper array bounds, where lowest bounds are 0
    ReDim Members(Parsed(myObject).Count - 1, 1)
      
    i = 0
    For Each Member In Parsed(myObject)
        Members(i, 0) = Member("id")
        Members(i, 1) = Member("fullName")

        i = i + 1
    Next Member
    NumberOfMembers = i
    
End Sub





Private Function FindActionListName(Action As Dictionary)
    cardMovedColumn = False
    On Error GoTo ErrHandler1
    FindActionListName = Action("data")("list")("name")
    Exit Function
    
TryNext1:
    On Error GoTo ErrHandler2
    FindActionListName = Action("data")("listAfter")("name")
    cardMovedColumn = True
    Exit Function
    
TryNext2:
    FindActionListName = "not found"
    Exit Function
    
ErrHandler1:
    Resume TryNext1
ErrHandler2:
    Resume TryNext2
        
End Function


Private Function FindActionCardName(Action As Dictionary)
    On Error GoTo ErrHandler1
    FindActionCardName = Action("data")("card")("name")
    Exit Function
    
TryNext1:
    FindActionCardName = "not found"
    Exit Function
        
ErrHandler1:
    Resume TryNext1
    
End Function

Private Sub FormatSheet(Sheet As String, StartRow As Integer)
'   Apply formatting to the header:
    Sheets(Sheet).Rows("1:3").Style = "Ênfase1"
    
    With Sheets(Sheet).Rows("2:3")
        .HorizontalAlignment = xlLeft
        .VerticalAlignment = xlTop
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
    End With
    
    With Sheets(Sheet).Range("C1")
        .HorizontalAlignment = xlLeft
        .VerticalAlignment = xlCenter
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
        .RowHeight = 50
        .Font.Bold = True
        .Font.Size = 26
    End With
    
    With Sheets(Sheet).Range("D2:D3")
        .HorizontalAlignment = xlRight
        .VerticalAlignment = xlTop
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
    End With
    
    With Sheets(Sheet).Range("G2:G3")
        .HorizontalAlignment = xlRight
        .VerticalAlignment = xlTop
        .WrapText = False
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
    End With
    
    With Sheets(Sheet).Rows(StartRow)
        .Style = "Ênfase1"
        .HorizontalAlignment = xlCenter
        .VerticalAlignment = xlCenter
        .WrapText = True
        .Orientation = 0
        .AddIndent = False
        .IndentLevel = 0
        .ShrinkToFit = False
        .ReadingOrder = xlContext
        .MergeCells = False
        .RowHeight = 40
        .Font.Bold = True
    End With
    
    With Sheets(Sheet).Range("A3")
        .Style = "Hyperlink"
    End With
    
End Sub


segunda-feira, 24 de março de 2025

Técnica dos Dois Passos no ChatGPT

 

Técnica dos Dois Passos no ChatGPT

Introdução

A técnica dos dois passos é uma forma otimizada de utilizar o ChatGPT para obter respostas mais precisas e elaboradas. Em vez de fazer uma pergunta direta, você primeiro estabelece os critérios ideais para a resposta desejada e só então solicita a análise ou geração de conteúdo.

Relação com a Engenharia de Prompt

A técnica dos dois passos está diretamente ligada à Engenharia de Prompt (Prompt Engineering), que é a arte de estruturar perguntas e comandos para obter respostas mais eficazes da IA. Ela se baseia em dois princípios fundamentais:

  1. Contextualização Progressiva: Criar um contexto detalhado antes da solicitação principal melhora a precisão das respostas geradas pelo ChatGPT.

  2. Divisão de Tarefas: Separar uma solicitação em dois passos permite que a IA compreenda melhor a necessidade do usuário antes de produzir um resultado final.

Ao aplicar essa técnica, você maximiza a qualidade das respostas e torna sua interação com a IA mais eficiente.

Como Funciona a Técnica dos Dois Passos

Exemplo de Uso

Imagine que você deseja que o ChatGPT analise um contrato de aluguel. Em vez de apenas pedir "Analise este contrato", você pode seguir os dois passos abaixo:

  1. Definir os Critérios Ideais

    • Pergunte: "O que faz um contrato de aluguel ser excelente?"

    • O ChatGPT listará os princípios e boas práticas que tornam um contrato bem elaborado.

  2. Aplicar os Critérios na Análise

    • Com base na resposta anterior, você solicita: "Agora use esses princípios para analisar o meu contrato."

Dessa forma, o ChatGPT tem um contexto mais rico para fornecer uma análise mais precisa e estruturada.


Aplicabilidade da Técnica

Essa metodologia pode ser aplicada em diversas situações, como:

  • Redação de textos: Pergunte "O que torna um artigo científico excelente?" antes de solicitar a redação.

  • Criação de modelos financeiros: Pergunte "Quais elementos um modelo financeiro precisa conter?" antes de pedir para gerar um modelo.

  • Análise de documentos: Pergunte "Quais são os principais critérios para avaliar um relatório financeiro?" antes de solicitar uma avaliação.

Benefícios da Técnica

  • Respostas mais precisas e completas

  • Maior controle sobre a qualidade do resultado

  • Possibilidade de aprendizado durante o processo

  • Melhoria na interação com o ChatGPT

Outros Exemplos de Aplicação

Aqui estão algumas situações onde a técnica dos dois passos pode ser utilizada:

  • Criação de um plano de negócios:

    1. Pergunte: "Quais são os elementos essenciais de um plano de negócios eficaz?"

    2. Depois, solicite: "Agora elabore um plano de negócios para minha empresa com base nesses elementos."

  • Melhoria na escrita de e-mails profissionais:

    1. Pergunte: "Quais são as melhores práticas para escrever um e-mail profissional persuasivo?"

    2. Depois, solicite: "Agora me ajude a escrever um e-mail seguindo essas práticas."

  • Desenvolvimento de um roteiro de apresentação:

    1. Pergunte: "O que faz um roteiro de apresentação ser impactante?"

    2. Depois, solicite: "Agora me ajude a criar um roteiro para minha apresentação com base nessas diretrizes."

  • Análise de um currículo:

    1. Pergunte: "O que faz um currículo se destacar no mercado de trabalho atual?"

    2. Depois, solicite: "Agora analise meu currículo com base nesses princípios."

  • Aprendizado de um novo idioma:

    1. Pergunte: "Quais são as melhores estratégias para aprender um novo idioma rapidamente?"

    2. Depois, solicite: "Agora crie um plano de estudos baseado nessas estratégias."

  • Criação de posts para redes sociais:

    1. Pergunte: "Quais elementos tornam um post para redes sociais mais engajador?"

    2. Depois, solicite: "Agora gere um post para minha marca seguindo essas diretrizes."

  • Estruturação de um código de programação:

    1. Pergunte: "Quais são as melhores práticas para escrever código limpo e eficiente em Python?"

    2. Depois, solicite: "Agora me ajude a refatorar esse código com base nessas práticas."

  • Preparação para entrevistas de emprego:

    1. Pergunte: "Quais são as perguntas mais comuns em entrevistas para minha área de atuação?"

    2. Depois, solicite: "Agora me ajude a elaborar respostas eficazes para essas perguntas."

Considerações Finais

A técnica dos dois passos é uma estratégia simples, mas extremamente eficaz para obter melhores resultados ao interagir com o ChatGPT. Sempre que precisar de uma resposta detalhada, comece estabelecendo os critérios de excelência antes de solicitar a tarefa principal.

segunda-feira, 13 de janeiro de 2025

Trazer em uma célula do Google Sheets,a Data Máxima de um conjunto de células.

Trazer em uma célula do Google Sheets,
a Data Máxima de um conjunto de células.

Vinha utilizando-se =MAX(X1:Y1).

Mas de um tempo para cá começou a retornar erros.

Passei a utilizar o SORTN. Coloquei para retornar o primeiro item de um conjunto de dados após a classificar decrescente. Caso deseje o mínimo, coloque para classificar em ordem crescente.

=SORTN(I3:I;1;0;1;FALSO)

Script para Registro de Edições no Google Sheets

 

Script para Registro de Edições no Google Sheets


Objetivo do Script

Este script tem como função registrar automaticamente a data, hora e a coluna editada na aba "Tratativa" de uma planilha do Google Sheets. O registro é feito em uma coluna específica (coluna 51) para facilitar a identificação das alterações realizadas.

Embora seja possível acessar essas informações clicando com o botão direito sobre a célula editada e verificando o histórico de edições, o script oferece uma forma prática e consolidada de acompanhar diretamente, em uma coluna separada, o que foi alterado nas outras colunas. Serve para um cenário com várias pessoas alterando a planilha.


Configuração Inicial

1. Inserção do Script

  1. Abra a planilha Google Sheets.
  2. Acesse Extensões > Apps Script.
  3. Substitua qualquer conteúdo existente pelo código abaixo:

javascript

function onEdit(e) {

    const sheet = e.source.getActiveSheet(); // Obtém a aba onde a edição ocorreu
    const sheetName = "Tratativa"; // Nome da planilha específica
    const range = e.range; // Local da edição
    const col = range.getColumn(); // Coluna editada
    const row = range.getRow(); // Linha editada
    const timestampCol = 51; // Coluna onde será registrado o horário e a coluna usada

    // Verifica se a edição ocorreu na planilha "Tratativa", entre as colunas 1 e 50, exceto na linha 1
    if (sheet.getName() === sheetName && col >= 1 && col <= 50 && row > 1) {
    const currentDate = new Date();
    const editedColumn = `Coluna ${col}`;
    const timestamp = currentDate.toLocaleString(); // Horário formatado

    // Concatena o horário e a coluna editada
    const logMessage = `${timestamp} - ${editedColumn}`;
    sheet.getRange(row, timestampCol).setValue(logMessage); // Escreve na coluna 51
    }
}

  1. Salve o projeto (ex.: "LogEdit").
  2. O script está pronto para uso.

Funcionamento do Script

  1. Monitoramento de Edições
    • O script é acionado automaticamente sempre que uma célula é editada na aba "Tratativa".
    • Ele monitora edições nas colunas 1 a 50 (A até AX) e ignora alterações na linha 1.
  2. Registro do Log
    • Para cada edição válida:
      • O script captura a data e hora atuais.
      • Identifica a coluna editada.
      • Registra uma mensagem no formato DD/MM/AAAA HH:MM - Coluna X na coluna 51 (coluna AY) da mesma linha.

Personalizações

1. Alterar o Nome da Aba

Caso deseje usar o script em outra aba, altere a linha:

javascript

const sheetName = "NovoNomeDaAba";

2. Modificar o Alcance de Colunas Monitoradas

Para ajustar as colunas que serão monitoradas, edite a condição:

javascript

if (col >= X && col <= Y)

Substitua X e Y pelos números das colunas desejadas.

3. Alterar a Coluna de Registro

Para que o log seja registrado em outra coluna, modifique o valor da variável timestampCol:

javascript

const timestampCol = NovaColuna;


Restrições

  • Aba específica: Apenas monitora a aba chamada "Tratativa".
  • Edições manuais: Não registra alterações feitas por fórmulas ou scripts automáticos.

Exemplo de Uso

  1. Um usuário edita a célula B3 da aba "Tratativa".
  2. O script registra na célula AY3:

13/01/2025 14:35 - Coluna 2


Resolução de Problemas

1. O script não está funcionando.

  • Certifique-se de que a aba tem o nome "Tratativa".
  • Verifique se as edições estão ocorrendo nas colunas 1 a 50 e abaixo da linha 1.

2. O log aparece na coluna errada.

  • Confirme o valor da variável timestampCol.