0
# Comments
1
2
Document commenting system for adding and managing comments anchored to specific text ranges. Provides collaborative features for document review and annotation.
3
4
## Capabilities
5
6
### Comment Management
7
8
Access and manage the document comments collection.
9
10
```python { .api }
11
class Document:
12
@property
13
def comments(self):
14
"""Collection of all comments in document.
15
16
Returns:
17
Comments: Comments collection object
18
"""
19
20
def add_comment(self, runs, text='', author='', initials=''):
21
"""Add a comment to the document.
22
23
Args:
24
runs (Run or list[Run]): Run or sequence of runs to anchor comment to
25
text (str, optional): Comment text content
26
author (str, optional): Comment author name
27
initials (str, optional): Author initials
28
29
Returns:
30
Comment: New comment object
31
"""
32
33
class Comments:
34
def add_comment(self, runs, text='', author='', initials=''):
35
"""Add a comment anchored to specified runs.
36
37
Args:
38
runs (Run or list[Run]): Run or sequence of runs to comment on
39
text (str, optional): Comment text content
40
author (str, optional): Comment author name
41
initials (str, optional): Author initials
42
43
Returns:
44
Comment: New comment object
45
"""
46
47
def __len__(self):
48
"""Number of comments in collection."""
49
50
def __iter__(self):
51
"""Iterate over comments."""
52
53
def __getitem__(self, index):
54
"""Access comment by index."""
55
```
56
57
**Usage Examples:**
58
59
```python
60
# Access comments collection
61
comments = doc.comments
62
print(f"Document has {len(comments)} comments")
63
64
# Add comment to a single run
65
para = doc.add_paragraph('This text will have a comment.')
66
run = para.runs[0]
67
comment = doc.add_comment(run, 'This is a comment', author='John Doe', initials='JD')
68
69
# Add comment through comments collection
70
comment2 = comments.add_comment(run, 'Another comment', author='Jane Smith')
71
72
# Iterate through all comments
73
for i, comment in enumerate(comments):
74
print(f"Comment {i+1}: {comment.text} by {comment.author}")
75
```
76
77
### Creating Comments
78
79
Add comments to specific text ranges with various anchoring options.
80
81
**Usage Examples:**
82
83
```python
84
# Add comment to single run
85
para = doc.add_paragraph('Text with comment.')
86
run = para.runs[0]
87
comment = doc.add_comment(run, 'Review this text', author='Reviewer')
88
89
# Add comment to multiple runs (text span)
90
para = doc.add_paragraph()
91
run1 = para.add_run('Start of ')
92
run2 = para.add_run('commented text ')
93
run3 = para.add_run('end.')
94
95
# Comment spans multiple runs
96
commented_runs = [run1, run2]
97
comment = doc.add_comment(commented_runs, 'This spans multiple runs',
98
author='Editor', initials='ED')
99
100
# Add comment with detailed information
101
para = doc.add_paragraph('Important information here.')
102
run = para.runs[0]
103
comment = doc.add_comment(
104
run,
105
'Please verify this information with the latest data.',
106
author='Data Analyst',
107
initials='DA'
108
)
109
110
# Add empty comment (to be filled later)
111
comment = doc.add_comment(run, author='Placeholder')
112
```
113
114
### Comment Properties
115
116
Access and manage comment properties and content.
117
118
```python { .api }
119
class Comment:
120
@property
121
def text(self):
122
"""Comment text content (read-only).
123
124
Returns:
125
str: Plain text content of all comment paragraphs
126
"""
127
128
@property
129
def author(self):
130
"""Comment author (read-only).
131
132
Returns:
133
str: Author name
134
"""
135
136
@property
137
def initials(self):
138
"""Author initials (read-only).
139
140
Returns:
141
str: Author initials
142
"""
143
144
@property
145
def paragraphs(self):
146
"""Paragraphs in the comment.
147
148
Returns:
149
list[Paragraph]: List of paragraph objects in comment
150
"""
151
152
@property
153
def tables(self):
154
"""Tables in the comment.
155
156
Returns:
157
list[Table]: List of table objects in comment
158
"""
159
160
def add_paragraph(self, text='', style=None):
161
"""Add a paragraph to the comment.
162
163
Args:
164
text (str, optional): Paragraph text
165
style (str or ParagraphStyle, optional): Paragraph style
166
167
Returns:
168
Paragraph: New paragraph object
169
"""
170
171
def add_table(self, rows, cols):
172
"""Add a table to the comment.
173
174
Args:
175
rows (int): Number of initial rows
176
cols (int): Number of initial columns
177
178
Returns:
179
Table: New table object
180
"""
181
```
182
183
**Usage Examples:**
184
185
```python
186
# Create comment and access properties
187
para = doc.add_paragraph('Commented text')
188
run = para.runs[0]
189
comment = doc.add_comment(run, 'Initial comment', author='John Doe', initials='JD')
190
191
# Access comment properties
192
print(f"Author: {comment.author}")
193
print(f"Initials: {comment.initials}")
194
print(f"Text: {comment.text}")
195
196
# Add additional content to comment
197
additional_para = comment.add_paragraph('Additional comment details.')
198
additional_para.runs[0].italic = True
199
200
# Add formatted content
201
formatted_para = comment.add_paragraph()
202
formatted_para.add_run('Bold comment text').bold = True
203
formatted_para.add_run(' and normal text.')
204
205
# Add table to comment
206
comment_table = comment.add_table(rows=2, cols=2)
207
comment_table.cell(0, 0).text = 'Issue'
208
comment_table.cell(0, 1).text = 'Status'
209
comment_table.cell(1, 0).text = 'Grammar'
210
comment_table.cell(1, 1).text = 'Fixed'
211
212
# Access all paragraphs in comment
213
for para in comment.paragraphs:
214
print(f"Comment paragraph: {para.text}")
215
```
216
217
### Advanced Comment Usage
218
219
Complex scenarios for document review and collaboration.
220
221
**Usage Examples:**
222
223
```python
224
# Create review workflow with multiple comments
225
def add_review_comment(run, issue_type, description, reviewer):
226
"""Add structured review comment."""
227
comment = doc.add_comment(run, '', author=reviewer)
228
229
# Add issue type header
230
header = comment.add_paragraph(f"{issue_type.upper()}", style='Strong')
231
232
# Add description
233
desc_para = comment.add_paragraph(description)
234
235
# Add reviewer signature
236
sig_para = comment.add_paragraph(f"- {reviewer}")
237
sig_para.runs[0].italic = True
238
239
return comment
240
241
# Usage of review function
242
para = doc.add_paragraph('This sentence has a potential issue.')
243
run = para.runs[0]
244
245
# Add different types of review comments
246
add_review_comment(run, 'Grammar', 'Check subject-verb agreement', 'Copy Editor')
247
add_review_comment(run, 'Fact Check', 'Verify statistics mentioned', 'Research Team')
248
add_review_comment(run, 'Style', 'Consider more concise wording', 'Style Guide Team')
249
250
# Create comment thread simulation
251
base_comment = doc.add_comment(run, 'Original comment', author='Author')
252
reply_para = base_comment.add_paragraph('Reply to comment')
253
reply_para.add_run(' - Reviewer Response').italic = True
254
255
# Add comment with action items
256
action_comment = doc.add_comment(run, '', author='Project Manager')
257
action_comment.add_paragraph('Action Items:')
258
259
action_table = action_comment.add_table(rows=3, cols=3)
260
headers = ['Task', 'Assignee', 'Due Date']
261
for i, header in enumerate(headers):
262
action_table.cell(0, i).text = header
263
action_table.cell(0, i).paragraphs[0].runs[0].bold = True
264
265
# Add action items
266
tasks = [
267
['Revise paragraph', 'Writer', '2024-01-15'],
268
['Review changes', 'Editor', '2024-01-17']
269
]
270
271
for row_idx, task_data in enumerate(tasks, 1):
272
for col_idx, data in enumerate(task_data):
273
action_table.cell(row_idx, col_idx).text = data
274
```
275
276
### Comment Analysis and Reporting
277
278
Analyze and report on document comments.
279
280
**Usage Examples:**
281
282
```python
283
def analyze_comments(doc):
284
"""Analyze document comments and generate report."""
285
comments = doc.comments
286
287
if len(comments) == 0:
288
print("No comments in document")
289
return
290
291
# Count comments by author
292
author_counts = {}
293
for comment in comments:
294
author = comment.author or 'Unknown'
295
author_counts[author] = author_counts.get(author, 0) + 1
296
297
print(f"Total comments: {len(comments)}")
298
print("\nComments by author:")
299
for author, count in author_counts.items():
300
print(f" {author}: {count}")
301
302
# List all comments
303
print("\nAll comments:")
304
for i, comment in enumerate(comments, 1):
305
print(f"{i}. [{comment.author or 'Unknown'}] {comment.text[:100]}...")
306
307
# Usage
308
analyze_comments(doc)
309
310
def extract_comment_text(doc):
311
"""Extract all comment text for analysis."""
312
all_comment_text = []
313
314
for comment in doc.comments:
315
# Get main comment text
316
main_text = comment.text
317
318
# Get text from all paragraphs (more detailed)
319
detailed_text = '\n'.join(para.text for para in comment.paragraphs)
320
321
all_comment_text.append({
322
'author': comment.author,
323
'initials': comment.initials,
324
'text': main_text,
325
'detailed_text': detailed_text
326
})
327
328
return all_comment_text
329
330
# Extract comment data
331
comment_data = extract_comment_text(doc)
332
for comment_info in comment_data:
333
print(f"Author: {comment_info['author']}")
334
print(f"Text: {comment_info['text']}")
335
print("---")
336
```
337
338
### Programmatic Comment Creation
339
340
Create comments programmatically for automated review processes.
341
342
**Usage Examples:**
343
344
```python
345
import re
346
347
def add_spell_check_comments(doc):
348
"""Add comments for potential spelling issues."""
349
# Simple spell check simulation
350
potential_errors = ['teh', 'recieve', 'occured', 'seperate']
351
352
for para in doc.paragraphs:
353
for error in potential_errors:
354
if error in para.text.lower():
355
# Find the run containing the error
356
for run in para.runs:
357
if error in run.text.lower():
358
comment = doc.add_comment(
359
run,
360
f'Possible spelling error: "{error}"',
361
author='Spell Checker',
362
initials='SC'
363
)
364
break
365
366
def add_length_comments(doc, max_sentence_length=25):
367
"""Add comments for overly long sentences."""
368
for para in doc.paragraphs:
369
sentences = re.split(r'[.!?]+', para.text)
370
for sentence in sentences:
371
words = sentence.strip().split()
372
if len(words) > max_sentence_length:
373
# Find run containing long sentence
374
for run in para.runs:
375
if sentence.strip() in run.text:
376
comment = doc.add_comment(
377
run,
378
f'Long sentence ({len(words)} words). Consider breaking up.',
379
author='Style Checker',
380
initials='ST'
381
)
382
break
383
384
# Apply automated commenting
385
add_spell_check_comments(doc)
386
add_length_comments(doc)
387
388
def add_consistency_comments(doc, style_guide):
389
"""Add comments for style guide violations."""
390
violations = {
391
'passive_voice': r'\b(was|were|is|are|been)\s+\w+ed\b',
392
'weak_words': r'\b(very|really|quite|rather)\b',
393
'contractions': r"\b\w+'\w+\b"
394
}
395
396
for para in doc.paragraphs:
397
for violation_type, pattern in violations.items():
398
matches = re.finditer(pattern, para.text, re.IGNORECASE)
399
for match in matches:
400
# Find the run containing the match
401
for run in para.runs:
402
if match.group() in run.text:
403
comment = doc.add_comment(
404
run,
405
f'Style guide: {violation_type.replace("_", " ").title()}',
406
author='Style Guide Bot',
407
initials='SG'
408
)
409
break
410
411
# Apply style guide checking
412
style_guide = {} # Style guide configuration
413
add_consistency_comments(doc, style_guide)
414
```
415
416
## Usage Patterns
417
418
### Document Review Workflow
419
420
```python
421
# Complete document review workflow
422
def setup_document_review(doc, reviewers):
423
"""Set up document for review process."""
424
# Add review instructions in document
425
instructions = doc.add_paragraph('REVIEW INSTRUCTIONS:', style='Strong')
426
doc.add_paragraph('Please add comments to sections that need attention.')
427
doc.add_paragraph('Use your initials when adding comments.')
428
doc.add_page_break()
429
430
# Track reviewers
431
reviewer_info = {}
432
for reviewer in reviewers:
433
name, initials = reviewer.split('|')
434
reviewer_info[initials] = name
435
436
return reviewer_info
437
438
def finalize_review(doc):
439
"""Generate review summary."""
440
comments = doc.comments
441
442
# Add summary section
443
doc.add_page_break()
444
doc.add_heading('Review Summary', level=1)
445
446
if len(comments) == 0:
447
doc.add_paragraph('No comments were added during review.')
448
return
449
450
# Create summary table
451
summary_table = doc.add_table(rows=1, cols=4)
452
headers = ['#', 'Author', 'Comment', 'Status']
453
for i, header in enumerate(headers):
454
summary_table.cell(0, i).text = header
455
summary_table.cell(0, i).paragraphs[0].runs[0].bold = True
456
457
# Add comment data
458
for i, comment in enumerate(comments, 1):
459
row = summary_table.add_row()
460
row.cells[0].text = str(i)
461
row.cells[1].text = comment.author or 'Unknown'
462
row.cells[2].text = comment.text[:100] + ('...' if len(comment.text) > 100 else '')
463
row.cells[3].text = 'Open'
464
465
# Usage
466
reviewers = ['John Doe|JD', 'Jane Smith|JS', 'Bob Wilson|BW']
467
reviewer_info = setup_document_review(doc, reviewers)
468
469
# ... document review process ...
470
471
finalize_review(doc)
472
```