Trabaja con comentarios y sugerencias

Documentos de Google permite que los colaboradores trabajen juntos escribiendo comentarios y haciendo sugerencias que actúan como ediciones diferidas que esperan aprobación.

Puedes usar la API para ver los cambios sugeridos intercalados en el texto del documento. En la versión preliminar para desarrolladores, también puedes leer, crear, responder, actualizar o borrar de forma programática los comentarios y los hilos de sugerencias.

Cuando usas el documents.get método para recuperar el contenido del documento, es posible que este incluya sugerencias sin resolver. Para controlar cómo documents.get representa las sugerencias, usa el parámetro opcional SuggestionsViewMode parámetro. Con este parámetro, están disponibles las siguientes condiciones de filtro:

  • Obtén contenido con SUGGESTIONS_INLINE, de modo que el texto pendiente de eliminación o inserción aparezca en el documento.
  • Obtén contenido como vista previa con todas las sugerencias aceptadas.
  • Obtén contenido como vista previa, sin sugerencias, con todas las sugerencias rechazadas.

Si no proporcionas SuggestionsViewMode, la API de Documentos de Google usa una configuración predeterminada adecuada para los privilegios del usuario actual.

Sugerencias e índices

Una razón por la que SuggestionsViewMode es importante es que los índices de la respuesta pueden variar según si hay sugerencias, como se muestra a continuación.

Contenido con sugerencias Contenido sin sugerencias
{
 "tabs": [
  {
   "documentTab": {
    "body": {
     "content": [
      {
       "startIndex": 1,
       "endIndex": 31,
       "paragraph": {
        "elements": [
         {
          "startIndex": 1,
          "endIndex": 31,
          "textRun": {
           "content": "Text preceding the suggestion\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      },
      {
       "startIndex": 31,
       "endIndex": 51,
       "paragraph": {
        "elements": [
         {
          "startIndex": 31,
          "endIndex": 50,
          "textRun": {
           "content": "Suggested insertion",
           "suggestedInsertionIds": [
            "suggest.vcti8ewm4mww"
           ],
           "textStyle": {}
          }
         },
         {
          "startIndex": 50,
          "endIndex": 51,
          "textRun": {
           "content": "\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      },
      {
       "startIndex": 51,
       "endIndex": 81,
       "paragraph": {
        "elements": [
         {
          "startIndex": 51,
          "endIndex": 81,
          "textRun": {
           "content": "Text following the suggestion\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      }
     ]
    }
   }
  }
 ]
},

{
 "tabs": [
  {
   "documentTab": {
    "body": {
     "content": [
      {
       "startIndex": 1,
       "endIndex": 31,
       "paragraph": {
        "elements": [
         {
          "startIndex": 1,
          "endIndex": 31,
          "textRun": {
           "content": "Text preceding the suggestion\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      },
      {
       "startIndex": 31,
       "endIndex": 32,
       "paragraph": {
        "elements": [
         {
          "startIndex": 31,
          "endIndex": 32,
          "textRun": {
           "content": "\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      },
      {
       "startIndex": 32,
       "endIndex": 62,
       "paragraph": {
        "elements": [
         {
          "startIndex": 32,
          "endIndex": 62,
          "textRun": {
           "content": "Text following the suggestion\n",
           "textStyle": {}
          }
         }
        ],
        "paragraphStyle": {
         "namedStyleType": "NORMAL_TEXT",
         "direction": "LEFT_TO_RIGHT"
        }
       }
      }
     ]
    }
   }
  }
 ]
},

En la respuesta anterior, el párrafo que contiene la línea "Texto después de la sugerencia" muestra la diferencia cuando se usa SuggestionsViewMode. Con el valor establecido en SUGGESTIONS_INLINE, el startIndex de la ParagraphElement comienza en 51 y el endIndex se detiene en 81. Sin sugerencias, el rango startIndex y endIndex es de 32 a 62.

Obtén contenido sin sugerencias

En el siguiente ejemplo de código parcial, se muestra cómo obtener un documento como vista previa con todas las sugerencias rechazadas (si las hay) configurando el parámetro SuggestionsViewMode en PREVIEW_WITHOUT_SUGGESTIONS.

Java

final string SUGGEST_MODE = "PREVIEW_WITHOUT_SUGGESTIONS";
Document doc =
    service
        .documents()
        .get(DOCUMENT_ID)
        .setIncludeTabsContent(true)
        .setSuggestionsViewMode(SUGGEST_MODE)
        .execute();

Python

SUGGEST_MODE = "PREVIEW_WITHOUT_SUGGESTIONS"
result = (
  service.documents()
  .get(
      documentId=DOCUMENT_ID,
      includeTabsContent=True,
      suggestionsViewMode=SUGGEST_MODE,
  )
  .execute()
)

Omitir el parámetro SuggestionsViewMode equivale a proporcionar DEFAULT_FOR_CURRENT_ACCESS como valor del parámetro.

Sugerencias de estilo

Los documentos también pueden tener sugerencias de estilo. Se trata de cambios sugeridos en el formato y la presentación, en lugar de cambios en el contenido.

A diferencia de las inserciones o eliminaciones de texto, estas no compensan los índices, aunque pueden dividir un TextRun en fragmentos más pequeños, sino que solo agregan anotaciones sobre el cambio de estilo sugerido.

Una de esas anotaciones es un SuggestedTextStyle, que consta de 2 partes:

  • El textStyle, que describe cómo se aplica el estilo al texto después del cambio sugerido, pero no indica qué cambió.

  • El textStyleSuggestionState, que indica cómo la sugerencia altera los campos del textStyle.

Puedes ver esto en el siguiente extracto de la pestaña del documento, que incluye un cambio de estilo sugerido:

[01] "paragraph": {
[02]    "elements": [
[03]        {
[04]            "endIndex": 106,
[05]            "startIndex": 82,
[06]            "textRun": {
[07]                "content": "Some text that does not ",
[08]                "textStyle": {}
[09]            }
[10]        },
[11]        {
[12]            "endIndex": 115,
[13]            "startIndex": 106,
[14]            "textRun": {
[15]                "content": "initially",
[16]                "suggestedTextStyleChanges": {
[17]                    "suggest.xymysbs9zldp": {
[18]                        "textStyle": {
[19]                            "backgroundColor": {},
[20]                            "baselineOffset": "NONE",
[21]                            "bold": true,
[22]                            "fontSize": {
[23]                                "magnitude": 11,
[24]                                "unit": "PT"
[25]                            },
[26]                            "foregroundColor": {
[27]                                "color": {
[28]                                    "rgbColor": {}
[29]                                }
[30]                            },
[31]                            "italic": false,
[32]                            "smallCaps": false,
[33]                            "strikethrough": false,
[34]                            "underline": false
[35]                        },
[36]                        "textStyleSuggestionState": {
[37]                            "boldSuggested": true,
[38]                            "weightedFontFamilySuggested": true
[39]                        }
[40]                    }
[41]                },
[42]                "textStyle": {
[43]                    "italic": true
[44]                }
[45]            }
[46]        },
[47]        {
[48]            "endIndex": 143,
[49]            "startIndex": 115,
[50]            "textRun": {
[51]                "content": " contain any boldface text.\n",
[52]                "textStyle": {}
[53]            }
[54]        }
[55]    ],
[56]    "paragraphStyle": {
[57]        "direction": "LEFT_TO_RIGHT",
[58]        "namedStyleType": "NORMAL_TEXT"
[59]    }
[60] }

En el ejemplo anterior, el párrafo consta de 3 ejecuciones de texto, que comienzan en las líneas 6, 14 y 50. Examina la ejecución de texto del medio:

  • Línea 16: Hay un objeto suggestedTextStyleChanges.
  • Línea 18: El textStyle especifica varios formatos.
  • Línea 36: El textStyleSuggestionState te indica que solo la parte en negrita de esta especificación era la sugerencia.
  • Línea 42: El estilo en cursiva de esta ejecución de texto forma parte del documento actual (y no se ve afectado por la sugerencia).

Solo las funciones de estilo establecidas en true en el textStyleSuggestionState forman parte de la sugerencia.

Crea y administra comentarios

Puedes agregar comentarios y respuestas, editar comentarios y borrar comentarios o respuestas de forma programática con el documents.batchUpdate método.

Cuando realices actualizaciones por lotes que involucren comentarios o sugerencias, debes supervisar las posibles fallas parciales. Para obtener más información, consulta Estado de actualización de comentarios y sugerencias.

Inserta un comentario

Para insertar un hilo de comentarios, usa el InsertCommentRequest objeto. Debes proporcionar el contenido del texto del comentario y una ubicación de anclaje (como un rango) donde se adjunta el comentario.

En el siguiente ejemplo de JSON, se agrega un hilo de comentarios no asignado al rango especificado:

{
  "requests": [
    {
      "insertComment": {
        "content": "This is a comment added via the API.",
        "range": {
          "startIndex": 10,
          "endIndex": 25
        }
      }
    }
  ]
}

Puedes asignar un comentario a un usuario específico si proporcionas su correo electrónico en el campo assigneeEmailAddress:

{
  "requests": [
    {
      "insertComment": {
        "content": "Please review this paragraph.",
        "assigneeEmailAddress": "user@example.com",
        "range": {
          "startIndex": 10,
          "endIndex": 25
        }
      }
    }
  ]
}

Agrega una respuesta o realiza una acción

Para responder a un comentario o hilo de sugerencias, o para resolver o volver a abrir un hilo, usa AddCommentReplyRequest.

Una respuesta se representa con un Post objeto. El objeto Post contiene la content de respuesta y, de manera opcional, puede especificar un commentAction (para RESOLVE o REOPEN el hilo).

En el siguiente ejemplo, se responde a un hilo de comentarios existente:

{
  "requests": [
    {
      "addCommentReply": {
        "commentId": "comment_thread_id",
        "post": {
          "content": "Replying to the comment thread."
        }
      }
    }
  ]
}

En el siguiente ejemplo, se resuelve un hilo de comentarios, que no requiere contenido:

{
  "requests": [
    {
      "addCommentReply": {
        "commentId": "comment_thread_id",
        "post": {
          "commentAction": "RESOLVE"
        }
      }
    }
  ]
}

Cómo editar una entrada

Para editar el contenido de texto de una entrada que creaste, usa UpdateCommentPostRequest. Debes especificar el ID del hilo (commentId o suggestionId), el postId de la entrada que quieres editar y el nuevo content de texto sin formato.

Ten en cuenta que no puedes editar la entrada principal de un hilo de sugerencias (ya que se generan mediante ediciones en modo de sugerencia).

{
  "requests": [
    {
      "updateCommentPost": {
        "commentId": "comment_thread_id",
        "postId": "post_id",
        "content": "This is the updated comment text."
      }
    }
  ]
}

Borra comentarios y respuestas

  • Borra un hilo de comentarios: Para quitar un hilo de comentarios completo, usa DeleteCommentRequest. Solo puedes borrar un hilo de comentarios si eres el autor de la entrada principal del hilo.
  • Borra una respuesta: Para borrar una entrada de respuesta específica, usa DeleteCommentReplyRequest. Solo puedes borrar las respuestas que creaste. No puedes borrar entradas de respuesta que contengan acciones o destinatarios.

En el siguiente ejemplo, se borra un hilo de comentarios:

{
  "requests": [
    {
      "deleteComment": {
        "commentId": "comment_thread_id"
      }
    }
  ]
}

Escribe sugerencias y administra hilos de sugerencias

Puedes escribir ediciones como sugerencias en lugar de ediciones directas y aceptar, rechazar o borrar hilos de sugerencias de forma programática.

Cuando realices actualizaciones por lotes que involucren sugerencias, debes supervisar las posibles fallas parciales. Para obtener más información, consulta Estado de actualización de comentarios y sugerencias.

Crea sugerencias con el modo de sugerencia

Para aplicar ediciones como sugerencias, establece el campo writeMode del objeto WriteControl en SUGGEST en tu solicitud de actualización por lotes. Todas las actualizaciones de la solicitud se procesan como sugerencias.

{
  "requests": [
    {
      "insertText": {
        "text": "suggested insertion text",
        "location": {
          "index": 1
        }
      }
    }
  ],
  "writeControl": {
    "writeMode": "SUGGEST"
  }
}

Solicitudes no compatibles en el modo de sugerencia

Cuando se usa WriteMode.SUGGEST, no se admiten los siguientes tipos de solicitudes y se mostrará un error:

  • AddDocumentTab
  • CreateNamedRange
  • DeleteFooter
  • DeleteHeader
  • DeleteNamedRange
  • DeleteTab
  • UpdateDocumentTabProperties
  • UpdateTableColumnProperties

Además, no puedes sugerir cambios en el formato del documento ni en la configuración de encabezados o pies de página. En UpdateDocumentStyle, no se admiten sugerencias para los siguientes tipos de estilo:

  • documentFormat
  • useEvenPageHeaderFooter
  • useFirstPageHeaderFooter

Acepta, rechaza o borra hilos de sugerencias

Puedes administrar hilos de sugerencias con las siguientes solicitudes:

  • Aceptar sugerencia: Usa AcceptSuggestionRequest para aceptar la sugerencia. Esto requiere acceso de edición al documento.
  • Rechazar sugerencia: Usa RejectSuggestionRequest para rechazar la sugerencia. Esto requiere acceso de edición al documento o ser el autor de la sugerencia.
  • Borrar sugerencia: Usa DeleteSuggestionRequest para borrar la sugerencia. Esto requiere ser el autor de la sugerencia.

En el siguiente ejemplo, se acepta un hilo de sugerencias:

{
  "requests": [
    {
      "acceptSuggestion": {
        "suggestionId": "suggestion_thread_id"
      }
    }
  ]
}

Estado de actualización de comentarios y sugerencias

Las solicitudes que requieren guardar comentarios o hilos de sugerencias (como insertar comentarios, agregar respuestas o hacer sugerencias) pueden experimentar fallas parciales. En estos casos, los cambios en el modelo del documento (como las inserciones o eliminaciones de texto) pueden confirmarse correctamente en el modelo de Documentos, pero es posible que no se guarden los comentarios o las sugerencias asociados.

Para verificar si las actualizaciones de comentarios o sugerencias se aplicaron correctamente, consulta el commentUpdateState field en el BatchUpdateDocumentResponse.

Los siguientes estados se muestran en CommentUpdateState:

  • NO_UPDATES_REQUESTED: No se solicitaron actualizaciones de comentarios ni sugerencias en la operación por lotes.
  • ALL_SAVED: Todas las actualizaciones de comentarios o sugerencias solicitadas se aplicaron correctamente.
  • ALL_FAILED_UNKNOWN_REASON: No se guardaron todas las actualizaciones de comentarios o sugerencias solicitadas, aunque se hayan confirmado los cambios en el modelo de Documentos.