[{"data":1,"prerenderedAt":2313},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Finsert-checkboxes-with-xlsxwriter":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Finsert-checkboxes-with-xlsxwriter":2280,"ancestors:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Finsert-checkboxes-with-xlsxwriter":2289,"children:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Finsert-checkboxes-with-xlsxwriter":2294,"related:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Finsert-checkboxes-with-xlsxwriter":2295},{"id":4,"title":5,"body":6,"dateModified":2247,"datePublished":2247,"description":2248,"extension":2249,"faq":2250,"keyword":2259,"kind":2260,"meta":2261,"navigation":235,"path":2269,"seo":2270,"slug":2273,"stem":2274,"topics":2275,"type":2278,"__hash__":2279},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Finsert-checkboxes-with-xlsxwriter\u002Findex.md","Insert Checkboxes in Excel with xlsxwriter",{"type":7,"value":8,"toc":2233},"minimark",[9,29,161,166,196,202,206,213,458,475,479,482,770,776,780,794,1334,1341,1568,1572,1575,1661,1669,1673,1679,1903,1915,1919,1922,2060,2075,2083,2087,2146,2150,2155,2159,2168,2172,2178,2184,2190,2196,2200,2229],[10,11,12,13,17,18,22,23,28],"p",{},"A checklist is one of the most common things people build in Excel: month-end close steps, audit sign-offs, onboarding tasks, a review column in a list of exceptions. For years the options were a TRUE\u002FFALSE dropdown or a fiddly form control floating over the cell. Microsoft 365 now has ",[14,15,16],"strong",{},"cell checkboxes"," — a boolean value in a cell, displayed as a box the reader can tick — and xlsxwriter can create them with ",[19,20,21],"code",{},"insert_checkbox",". This page, part of ",[24,25,27],"a",{"href":26},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002F","Building Excel Reports with xlsxwriter",", builds a month-end close checklist with checkboxes, a progress figure and finished rows struck through, and covers what happens in programs that do not support the feature.",[30,31,39,40,39,44,39,48,39,56,39,66,39,77,39,84,39,89,39,95,39,100,39,103,39,109,39,113,39,115,39,119,39,122,39,125,39,131,39,135,39,138,39,142,39,145,39,148,39,154,39,158],"svg",{"viewBox":32,"role":33,"ariaLabelledBy":34,"xmlns":37,"style":38},"4 0 752 125","img",[35,36],"cb-flow-t","cb-flow-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[41,42,43],"title",{"id":35},"From a list of steps to a live checklist",[45,46,47],"desc",{"id":36},"Four steps. Read the list of close steps with their Done flags. Write each Done flag with insert_checkbox. Add a progress formula counting TRUE values. Add conditional formatting that greys out and strikes through rows whose box is ticked.",[49,50],"rect",{"x":51,"y":52,"width":53,"height":54,"fill":55},"4","0","752","125","#ffffff",[49,57],{"x":58,"y":59,"width":60,"height":61,"rx":62,"fill":63,"stroke":64,"style":65},"20.0","16.0","153.0","93.0","12","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:2px",[67,68,70],"g",{"transform":69},"translate(84.5,29.0) scale(1.000)",[71,72],"path",{"d":73,"fill":74,"stroke":75,"style":76},"M3 5h18v14H3z M3 10h18 M3 15h18 M9 5v14","none","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[78,79,83],"text",{"x":80,"y":81,"style":82},"96.5","75.5","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Steps and flags",[78,85,88],{"x":80,"y":86,"style":87},"95.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","DataFrame",[90,91],"line",{"x1":92,"y1":93,"x2":94,"y2":93,"stroke":64,"style":65},"178.0","62.5","200.0",[96,97],"polygon",{"points":98,"fill":99},"204.0,62.5 195.0,67.5 195.0,57.5","#5b5cf0",[49,101],{"x":102,"y":59,"width":60,"height":61,"rx":62,"fill":63,"stroke":64,"style":65},"209.0",[67,104,106],{"transform":105},"translate(273.5,29.0) scale(1.000)",[71,107],{"d":108,"fill":74,"stroke":75,"style":76},"M5 12.5l4.5 4.5L19 7",[78,110,112],{"x":111,"y":81,"style":82},"285.5","Checkboxes",[78,114,21],{"x":111,"y":86,"style":87},[90,116],{"x1":117,"y1":93,"x2":118,"y2":93,"stroke":64,"style":65},"367.0","389.0",[96,120],{"points":121,"fill":99},"393.0,62.5 384.0,67.5 384.0,57.5",[49,123],{"x":124,"y":59,"width":60,"height":61,"rx":62,"fill":63,"stroke":64,"style":65},"398.0",[67,126,128],{"transform":127},"translate(462.5,29.0) scale(1.000)",[71,129],{"d":130,"fill":74,"stroke":75,"style":76},"M4 20h16 M7 17v-5 M12 17V7 M17 17v-8",[78,132,134],{"x":133,"y":81,"style":82},"474.5","Progress",[78,136,137],{"x":133,"y":86,"style":87},"COUNTIF(…, TRUE)",[90,139],{"x1":140,"y1":93,"x2":141,"y2":93,"stroke":64,"style":65},"556.0","578.0",[96,143],{"points":144,"fill":99},"582.0,62.5 573.0,67.5 573.0,57.5",[49,146],{"x":147,"y":59,"width":60,"height":61,"rx":62,"fill":63,"stroke":64,"style":65},"587.0",[67,149,151],{"transform":150},"translate(651.5,29.0) scale(1.000)",[71,152],{"d":153,"fill":74,"stroke":75,"style":76},"M3 5h18l-7 8v6l-4 2v-8z",[78,155,157],{"x":156,"y":81,"style":82},"663.5","Strike done rows",[78,159,160],{"x":156,"y":86,"style":87},"conditional format",[162,163,165],"h2",{"id":164},"prerequisites","Prerequisites",[167,168,173],"pre",{"className":169,"code":170,"language":171,"meta":172,"style":172},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install \"xlsxwriter>=3.2.1\" pandas openpyxl\n","bash","",[19,174,175],{"__ignoreMap":172},[176,177,179,183,187,190,193],"span",{"class":90,"line":178},1,[176,180,182],{"class":181},"sMTad","pip",[176,184,186],{"class":185},"srMev"," install",[176,188,189],{"class":185}," \"xlsxwriter>=3.2.1\"",[176,191,192],{"class":185}," pandas",[176,194,195],{"class":185}," openpyxl\n",[10,197,198,201],{},[19,199,200],{},"close_steps.xlsx"," lists six month-end close steps with an owner, a due date and whether each is done. Displaying checkboxes needs a current Microsoft 365 version of Excel; everywhere else the same cells show TRUE and FALSE.",[162,203,205],{"id":204},"step-1-insert-a-checkbox","Step 1 — Insert a checkbox",[10,207,208,209,212],{},"A checkbox is a boolean cell with a special format. ",[19,210,211],{},"insert_checkbox(row, col, value)"," writes the boolean and applies that format in one call:",[167,214,218],{"className":215,"code":216,"language":217,"meta":172,"style":172},"language-python shiki shiki-themes github-light github-dark-high-contrast","import xlsxwriter\n\nbook = xlsxwriter.Workbook(\"checkbox_basics.xlsx\")\nsheet = book.add_worksheet(\"Tasks\")\nsheet.write_row(0, 0, [\"Task\", \"Done\"], book.add_format({\"bold\": True}))\nsheet.write(1, 0, \"Send invoices\");   sheet.insert_checkbox(1, 1, True)\nsheet.write(2, 0, \"Chase INV-2150\");  sheet.insert_checkbox(2, 1, False)\nsheet.set_column(0, 0, 20)\nbook.close()\n\nfrom openpyxl import load_workbook\nprint([(c.value, c.data_type) for c in load_workbook(\"checkbox_basics.xlsx\").active[\"B\"][1:]])\n","python",[19,219,220,230,237,255,271,311,344,377,396,402,407,421],{"__ignoreMap":172},[176,221,222,226],{"class":90,"line":178},[176,223,225],{"class":224},"s-kum","import",[176,227,229],{"class":228},"skGVy"," xlsxwriter\n",[176,231,233],{"class":90,"line":232},2,[176,234,236],{"emptyLinePlaceholder":235},true,"\n",[176,238,240,243,246,249,252],{"class":90,"line":239},3,[176,241,242],{"class":228},"book ",[176,244,245],{"class":224},"=",[176,247,248],{"class":228}," xlsxwriter.Workbook(",[176,250,251],{"class":185},"\"checkbox_basics.xlsx\"",[176,253,254],{"class":228},")\n",[176,256,258,261,263,266,269],{"class":90,"line":257},4,[176,259,260],{"class":228},"sheet ",[176,262,245],{"class":224},[176,264,265],{"class":228}," book.add_worksheet(",[176,267,268],{"class":185},"\"Tasks\"",[176,270,254],{"class":228},[176,272,274,277,280,283,285,288,291,293,296,299,302,305,308],{"class":90,"line":273},5,[176,275,276],{"class":228},"sheet.write_row(",[176,278,52],{"class":279},"sP0c6",[176,281,282],{"class":228},", ",[176,284,52],{"class":279},[176,286,287],{"class":228},", [",[176,289,290],{"class":185},"\"Task\"",[176,292,282],{"class":228},[176,294,295],{"class":185},"\"Done\"",[176,297,298],{"class":228},"], book.add_format({",[176,300,301],{"class":185},"\"bold\"",[176,303,304],{"class":228},": ",[176,306,307],{"class":279},"True",[176,309,310],{"class":228},"}))\n",[176,312,314,317,320,322,324,326,329,332,334,336,338,340,342],{"class":90,"line":313},6,[176,315,316],{"class":228},"sheet.write(",[176,318,319],{"class":279},"1",[176,321,282],{"class":228},[176,323,52],{"class":279},[176,325,282],{"class":228},[176,327,328],{"class":185},"\"Send invoices\"",[176,330,331],{"class":228},");   sheet.insert_checkbox(",[176,333,319],{"class":279},[176,335,282],{"class":228},[176,337,319],{"class":279},[176,339,282],{"class":228},[176,341,307],{"class":279},[176,343,254],{"class":228},[176,345,347,349,352,354,356,358,361,364,366,368,370,372,375],{"class":90,"line":346},7,[176,348,316],{"class":228},[176,350,351],{"class":279},"2",[176,353,282],{"class":228},[176,355,52],{"class":279},[176,357,282],{"class":228},[176,359,360],{"class":185},"\"Chase INV-2150\"",[176,362,363],{"class":228},");  sheet.insert_checkbox(",[176,365,351],{"class":279},[176,367,282],{"class":228},[176,369,319],{"class":279},[176,371,282],{"class":228},[176,373,374],{"class":279},"False",[176,376,254],{"class":228},[176,378,380,383,385,387,389,391,394],{"class":90,"line":379},8,[176,381,382],{"class":228},"sheet.set_column(",[176,384,52],{"class":279},[176,386,282],{"class":228},[176,388,52],{"class":279},[176,390,282],{"class":228},[176,392,393],{"class":279},"20",[176,395,254],{"class":228},[176,397,399],{"class":90,"line":398},9,[176,400,401],{"class":228},"book.close()\n",[176,403,405],{"class":90,"line":404},10,[176,406,236],{"emptyLinePlaceholder":235},[176,408,410,413,416,418],{"class":90,"line":409},11,[176,411,412],{"class":224},"from",[176,414,415],{"class":228}," openpyxl ",[176,417,225],{"class":224},[176,419,420],{"class":228}," load_workbook\n",[176,422,424,427,430,433,436,439,442,444,447,450,453,455],{"class":90,"line":423},12,[176,425,426],{"class":279},"print",[176,428,429],{"class":228},"([(c.value, c.data_type) ",[176,431,432],{"class":224},"for",[176,434,435],{"class":228}," c ",[176,437,438],{"class":224},"in",[176,440,441],{"class":228}," load_workbook(",[176,443,251],{"class":185},[176,445,446],{"class":228},").active[",[176,448,449],{"class":185},"\"B\"",[176,451,452],{"class":228},"][",[176,454,319],{"class":279},[176,456,457],{"class":228},":]])\n",[10,459,460,461,463,464,466,467,470,471,474],{},"The cells hold ",[19,462,307],{}," and ",[19,465,374],{}," with type ",[19,468,469],{},"b",", boolean. Clicking a box in Excel flips the value, and anything that reads the cell — a formula, pandas, openpyxl — sees a plain boolean. Rows and columns are zero-based, like every xlsxwriter method; ",[19,472,473],{},"insert_checkbox(\"B2\", True)"," with an A1 reference works too.",[162,476,478],{"id":477},"step-2-write-the-checklist-from-a-dataframe","Step 2 — Write the checklist from a DataFrame",[10,480,481],{},"pandas writes a boolean column as TRUE\u002FFALSE cells. Write the table with pandas, then overwrite the Done column with checkboxes through the same xlsxwriter worksheet:",[167,483,485],{"className":215,"code":484,"language":217,"meta":172,"style":172},"import pandas as pd\n\nsteps = pd.read_excel(\"close_steps.xlsx\")\ndone_col = steps.columns.get_loc(\"Done\")\nwith pd.ExcelWriter(\"close_checklist.xlsx\", engine=\"xlsxwriter\", datetime_format=\"dd mmm\") as writer:\n    steps.to_excel(writer, sheet_name=\"Close\", index=False, startrow=2)\n    ws = writer.sheets[\"Close\"]\n    for i, done in enumerate(steps[\"Done\"], start=3):\n        ws.insert_checkbox(i, done_col, bool(done))\n    ws.set_column(\"A:A\", 24)\n    ws.set_column(\"B:C\", 10)\n    ws.set_column(\"D:D\", 7)\n    ws.write(\"A1\", \"Month-end close — September 2026\", writer.book.add_format({\"bold\": True, \"font_size\": 14}))\nprint(steps[\"Done\"].sum(), \"of\", len(steps), \"done\")\n",[19,486,487,500,504,519,533,573,606,621,653,664,679,693,707,742],{"__ignoreMap":172},[176,488,489,491,494,497],{"class":90,"line":178},[176,490,225],{"class":224},[176,492,493],{"class":228}," pandas ",[176,495,496],{"class":224},"as",[176,498,499],{"class":228}," pd\n",[176,501,502],{"class":90,"line":232},[176,503,236],{"emptyLinePlaceholder":235},[176,505,506,509,511,514,517],{"class":90,"line":239},[176,507,508],{"class":228},"steps ",[176,510,245],{"class":224},[176,512,513],{"class":228}," pd.read_excel(",[176,515,516],{"class":185},"\"close_steps.xlsx\"",[176,518,254],{"class":228},[176,520,521,524,526,529,531],{"class":90,"line":257},[176,522,523],{"class":228},"done_col ",[176,525,245],{"class":224},[176,527,528],{"class":228}," steps.columns.get_loc(",[176,530,295],{"class":185},[176,532,254],{"class":228},[176,534,535,538,541,544,546,550,552,555,557,560,562,565,568,570],{"class":90,"line":273},[176,536,537],{"class":224},"with",[176,539,540],{"class":228}," pd.ExcelWriter(",[176,542,543],{"class":185},"\"close_checklist.xlsx\"",[176,545,282],{"class":228},[176,547,549],{"class":548},"sa561","engine",[176,551,245],{"class":224},[176,553,554],{"class":185},"\"xlsxwriter\"",[176,556,282],{"class":228},[176,558,559],{"class":548},"datetime_format",[176,561,245],{"class":224},[176,563,564],{"class":185},"\"dd mmm\"",[176,566,567],{"class":228},") ",[176,569,496],{"class":224},[176,571,572],{"class":228}," writer:\n",[176,574,575,578,581,583,586,588,591,593,595,597,600,602,604],{"class":90,"line":313},[176,576,577],{"class":228},"    steps.to_excel(writer, ",[176,579,580],{"class":548},"sheet_name",[176,582,245],{"class":224},[176,584,585],{"class":185},"\"Close\"",[176,587,282],{"class":228},[176,589,590],{"class":548},"index",[176,592,245],{"class":224},[176,594,374],{"class":279},[176,596,282],{"class":228},[176,598,599],{"class":548},"startrow",[176,601,245],{"class":224},[176,603,351],{"class":279},[176,605,254],{"class":228},[176,607,608,611,613,616,618],{"class":90,"line":346},[176,609,610],{"class":228},"    ws ",[176,612,245],{"class":224},[176,614,615],{"class":228}," writer.sheets[",[176,617,585],{"class":185},[176,619,620],{"class":228},"]\n",[176,622,623,626,629,631,634,637,639,642,645,647,650],{"class":90,"line":379},[176,624,625],{"class":224},"    for",[176,627,628],{"class":228}," i, done ",[176,630,438],{"class":224},[176,632,633],{"class":279}," enumerate",[176,635,636],{"class":228},"(steps[",[176,638,295],{"class":185},[176,640,641],{"class":228},"], ",[176,643,644],{"class":548},"start",[176,646,245],{"class":224},[176,648,649],{"class":279},"3",[176,651,652],{"class":228},"):\n",[176,654,655,658,661],{"class":90,"line":398},[176,656,657],{"class":228},"        ws.insert_checkbox(i, done_col, ",[176,659,660],{"class":279},"bool",[176,662,663],{"class":228},"(done))\n",[176,665,666,669,672,674,677],{"class":90,"line":404},[176,667,668],{"class":228},"    ws.set_column(",[176,670,671],{"class":185},"\"A:A\"",[176,673,282],{"class":228},[176,675,676],{"class":279},"24",[176,678,254],{"class":228},[176,680,681,683,686,688,691],{"class":90,"line":409},[176,682,668],{"class":228},[176,684,685],{"class":185},"\"B:C\"",[176,687,282],{"class":228},[176,689,690],{"class":279},"10",[176,692,254],{"class":228},[176,694,695,697,700,702,705],{"class":90,"line":423},[176,696,668],{"class":228},[176,698,699],{"class":185},"\"D:D\"",[176,701,282],{"class":228},[176,703,704],{"class":279},"7",[176,706,254],{"class":228},[176,708,710,713,716,718,721,724,726,728,730,732,735,737,740],{"class":90,"line":709},13,[176,711,712],{"class":228},"    ws.write(",[176,714,715],{"class":185},"\"A1\"",[176,717,282],{"class":228},[176,719,720],{"class":185},"\"Month-end close — September 2026\"",[176,722,723],{"class":228},", writer.book.add_format({",[176,725,301],{"class":185},[176,727,304],{"class":228},[176,729,307],{"class":279},[176,731,282],{"class":228},[176,733,734],{"class":185},"\"font_size\"",[176,736,304],{"class":228},[176,738,739],{"class":279},"14",[176,741,310],{"class":228},[176,743,745,747,749,751,754,757,759,762,765,768],{"class":90,"line":744},14,[176,746,426],{"class":279},[176,748,636],{"class":228},[176,750,295],{"class":185},[176,752,753],{"class":228},"].sum(), ",[176,755,756],{"class":185},"\"of\"",[176,758,282],{"class":228},[176,760,761],{"class":279},"len",[176,763,764],{"class":228},"(steps), ",[176,766,767],{"class":185},"\"done\"",[176,769,254],{"class":228},[10,771,772,775],{},[19,773,774],{},"bool(done)"," converts NumPy booleans to Python ones, which xlsxwriter expects. Starting the table at row 3 leaves room for a title and the progress line added next. The owners can now tick their steps directly in the shared workbook.",[162,777,779],{"id":778},"step-3-show-progress-with-formulas","Step 3 — Show progress with formulas",[10,781,782,783,786,787,790,791,793],{},"A ticked box is ",[19,784,785],{},"TRUE",", so ",[19,788,789],{},"COUNTIF(range, TRUE)"," counts them. xlsxwriter cannot calculate formulas and stores ",[19,792,52],{}," as their result unless you pass one; pass the value you already know from pandas, so viewers that do not recalculate — previews, pandas, openpyxl — see the right figure:",[167,795,797],{"className":215,"code":796,"language":217,"meta":172,"style":172},"first, last = 4, 3 + len(steps)\ndone_n = int(steps[\"Done\"].sum())\nwith pd.ExcelWriter(\"close_checklist.xlsx\", engine=\"xlsxwriter\", datetime_format=\"dd mmm\") as writer:\n    steps.to_excel(writer, sheet_name=\"Close\", index=False, startrow=2)\n    wb, ws = writer.book, writer.sheets[\"Close\"]\n    for i, done in enumerate(steps[\"Done\"], start=3):\n        ws.insert_checkbox(i, done_col, bool(done))\n    ws.write(\"A1\", \"Month-end close — September 2026\", wb.add_format({\"bold\": True, \"font_size\": 14}))\n    ws.write_formula(\"A2\", f'=COUNTIF(D{first}:D{last},TRUE)&\" of \"&ROWS(D{first}:D{last})&\" steps done\"',\n                     None, f\"{done_n} of {len(steps)} steps done\")\n    ws.write_formula(\"C2\", f\"=COUNTIF(D{first}:D{last},TRUE)\u002FROWS(D{first}:D{last})\",\n                     wb.add_format({\"num_format\": \"0%\", \"bold\": True}), done_n \u002F len(steps))\n    ws.set_column(\"A:A\", 24); ws.set_column(\"B:C\", 10); ws.set_column(\"D:D\", 7)\n    ws.conditional_format(f\"A{first}:D{last}\", {\"type\": \"formula\", \"criteria\": f\"=$D{first}=TRUE\",\n                          \"format\": wb.add_format({\"font_strikeout\": True, \"font_color\": \"#808080\"})})\n\nprint(load_workbook(\"close_checklist.xlsx\").active[\"A2\"].value)\nprint(pd.read_excel(\"close_checklist.xlsx\", header=None, nrows=2).iloc[1, [0, 2]].tolist())\n",[19,798,799,822,839,869,897,911,935,943,972,1031,1067,1117,1149,1178,1238,1267,1272,1289],{"__ignoreMap":172},[176,800,801,804,806,809,811,813,816,819],{"class":90,"line":178},[176,802,803],{"class":228},"first, last ",[176,805,245],{"class":224},[176,807,808],{"class":279}," 4",[176,810,282],{"class":228},[176,812,649],{"class":279},[176,814,815],{"class":224}," +",[176,817,818],{"class":279}," len",[176,820,821],{"class":228},"(steps)\n",[176,823,824,827,829,832,834,836],{"class":90,"line":232},[176,825,826],{"class":228},"done_n ",[176,828,245],{"class":224},[176,830,831],{"class":279}," int",[176,833,636],{"class":228},[176,835,295],{"class":185},[176,837,838],{"class":228},"].sum())\n",[176,840,841,843,845,847,849,851,853,855,857,859,861,863,865,867],{"class":90,"line":239},[176,842,537],{"class":224},[176,844,540],{"class":228},[176,846,543],{"class":185},[176,848,282],{"class":228},[176,850,549],{"class":548},[176,852,245],{"class":224},[176,854,554],{"class":185},[176,856,282],{"class":228},[176,858,559],{"class":548},[176,860,245],{"class":224},[176,862,564],{"class":185},[176,864,567],{"class":228},[176,866,496],{"class":224},[176,868,572],{"class":228},[176,870,871,873,875,877,879,881,883,885,887,889,891,893,895],{"class":90,"line":257},[176,872,577],{"class":228},[176,874,580],{"class":548},[176,876,245],{"class":224},[176,878,585],{"class":185},[176,880,282],{"class":228},[176,882,590],{"class":548},[176,884,245],{"class":224},[176,886,374],{"class":279},[176,888,282],{"class":228},[176,890,599],{"class":548},[176,892,245],{"class":224},[176,894,351],{"class":279},[176,896,254],{"class":228},[176,898,899,902,904,907,909],{"class":90,"line":273},[176,900,901],{"class":228},"    wb, ws ",[176,903,245],{"class":224},[176,905,906],{"class":228}," writer.book, writer.sheets[",[176,908,585],{"class":185},[176,910,620],{"class":228},[176,912,913,915,917,919,921,923,925,927,929,931,933],{"class":90,"line":313},[176,914,625],{"class":224},[176,916,628],{"class":228},[176,918,438],{"class":224},[176,920,633],{"class":279},[176,922,636],{"class":228},[176,924,295],{"class":185},[176,926,641],{"class":228},[176,928,644],{"class":548},[176,930,245],{"class":224},[176,932,649],{"class":279},[176,934,652],{"class":228},[176,936,937,939,941],{"class":90,"line":346},[176,938,657],{"class":228},[176,940,660],{"class":279},[176,942,663],{"class":228},[176,944,945,947,949,951,953,956,958,960,962,964,966,968,970],{"class":90,"line":379},[176,946,712],{"class":228},[176,948,715],{"class":185},[176,950,282],{"class":228},[176,952,720],{"class":185},[176,954,955],{"class":228},", wb.add_format({",[176,957,301],{"class":185},[176,959,304],{"class":228},[176,961,307],{"class":279},[176,963,282],{"class":228},[176,965,734],{"class":185},[176,967,304],{"class":228},[176,969,739],{"class":279},[176,971,310],{"class":228},[176,973,974,977,980,982,985,988,992,995,998,1001,1003,1006,1008,1011,1013,1015,1017,1019,1021,1023,1025,1028],{"class":90,"line":398},[176,975,976],{"class":228},"    ws.write_formula(",[176,978,979],{"class":185},"\"A2\"",[176,981,282],{"class":228},[176,983,984],{"class":224},"f",[176,986,987],{"class":185},"'=COUNTIF(D",[176,989,991],{"class":990},"sSjpA","{",[176,993,994],{"class":228},"first",[176,996,997],{"class":990},"}",[176,999,1000],{"class":185},":D",[176,1002,991],{"class":990},[176,1004,1005],{"class":228},"last",[176,1007,997],{"class":990},[176,1009,1010],{"class":185},",TRUE)&\" of \"&ROWS(D",[176,1012,991],{"class":990},[176,1014,994],{"class":228},[176,1016,997],{"class":990},[176,1018,1000],{"class":185},[176,1020,991],{"class":990},[176,1022,1005],{"class":228},[176,1024,997],{"class":990},[176,1026,1027],{"class":185},")&\" steps done\"'",[176,1029,1030],{"class":228},",\n",[176,1032,1033,1036,1038,1040,1043,1045,1048,1050,1053,1055,1057,1060,1062,1065],{"class":90,"line":404},[176,1034,1035],{"class":279},"                     None",[176,1037,282],{"class":228},[176,1039,984],{"class":224},[176,1041,1042],{"class":185},"\"",[176,1044,991],{"class":990},[176,1046,1047],{"class":228},"done_n",[176,1049,997],{"class":990},[176,1051,1052],{"class":185}," of ",[176,1054,991],{"class":990},[176,1056,761],{"class":279},[176,1058,1059],{"class":228},"(steps)",[176,1061,997],{"class":990},[176,1063,1064],{"class":185}," steps done\"",[176,1066,254],{"class":228},[176,1068,1069,1071,1074,1076,1078,1081,1083,1085,1087,1089,1091,1093,1095,1098,1100,1102,1104,1106,1108,1110,1112,1115],{"class":90,"line":409},[176,1070,976],{"class":228},[176,1072,1073],{"class":185},"\"C2\"",[176,1075,282],{"class":228},[176,1077,984],{"class":224},[176,1079,1080],{"class":185},"\"=COUNTIF(D",[176,1082,991],{"class":990},[176,1084,994],{"class":228},[176,1086,997],{"class":990},[176,1088,1000],{"class":185},[176,1090,991],{"class":990},[176,1092,1005],{"class":228},[176,1094,997],{"class":990},[176,1096,1097],{"class":185},",TRUE)\u002FROWS(D",[176,1099,991],{"class":990},[176,1101,994],{"class":228},[176,1103,997],{"class":990},[176,1105,1000],{"class":185},[176,1107,991],{"class":990},[176,1109,1005],{"class":228},[176,1111,997],{"class":990},[176,1113,1114],{"class":185},")\"",[176,1116,1030],{"class":228},[176,1118,1119,1122,1125,1127,1130,1132,1134,1136,1138,1141,1144,1146],{"class":90,"line":423},[176,1120,1121],{"class":228},"                     wb.add_format({",[176,1123,1124],{"class":185},"\"num_format\"",[176,1126,304],{"class":228},[176,1128,1129],{"class":185},"\"0%\"",[176,1131,282],{"class":228},[176,1133,301],{"class":185},[176,1135,304],{"class":228},[176,1137,307],{"class":279},[176,1139,1140],{"class":228},"}), done_n ",[176,1142,1143],{"class":224},"\u002F",[176,1145,818],{"class":279},[176,1147,1148],{"class":228},"(steps))\n",[176,1150,1151,1153,1155,1157,1159,1162,1164,1166,1168,1170,1172,1174,1176],{"class":90,"line":709},[176,1152,668],{"class":228},[176,1154,671],{"class":185},[176,1156,282],{"class":228},[176,1158,676],{"class":279},[176,1160,1161],{"class":228},"); ws.set_column(",[176,1163,685],{"class":185},[176,1165,282],{"class":228},[176,1167,690],{"class":279},[176,1169,1161],{"class":228},[176,1171,699],{"class":185},[176,1173,282],{"class":228},[176,1175,704],{"class":279},[176,1177,254],{"class":228},[176,1179,1180,1183,1185,1188,1190,1192,1194,1196,1198,1200,1202,1204,1207,1210,1212,1215,1217,1220,1222,1224,1227,1229,1231,1233,1236],{"class":90,"line":744},[176,1181,1182],{"class":228},"    ws.conditional_format(",[176,1184,984],{"class":224},[176,1186,1187],{"class":185},"\"A",[176,1189,991],{"class":990},[176,1191,994],{"class":228},[176,1193,997],{"class":990},[176,1195,1000],{"class":185},[176,1197,991],{"class":990},[176,1199,1005],{"class":228},[176,1201,997],{"class":990},[176,1203,1042],{"class":185},[176,1205,1206],{"class":228},", {",[176,1208,1209],{"class":185},"\"type\"",[176,1211,304],{"class":228},[176,1213,1214],{"class":185},"\"formula\"",[176,1216,282],{"class":228},[176,1218,1219],{"class":185},"\"criteria\"",[176,1221,304],{"class":228},[176,1223,984],{"class":224},[176,1225,1226],{"class":185},"\"=$D",[176,1228,991],{"class":990},[176,1230,994],{"class":228},[176,1232,997],{"class":990},[176,1234,1235],{"class":185},"=TRUE\"",[176,1237,1030],{"class":228},[176,1239,1241,1244,1247,1250,1252,1254,1256,1259,1261,1264],{"class":90,"line":1240},15,[176,1242,1243],{"class":185},"                          \"format\"",[176,1245,1246],{"class":228},": wb.add_format({",[176,1248,1249],{"class":185},"\"font_strikeout\"",[176,1251,304],{"class":228},[176,1253,307],{"class":279},[176,1255,282],{"class":228},[176,1257,1258],{"class":185},"\"font_color\"",[176,1260,304],{"class":228},[176,1262,1263],{"class":185},"\"#808080\"",[176,1265,1266],{"class":228},"})})\n",[176,1268,1270],{"class":90,"line":1269},16,[176,1271,236],{"emptyLinePlaceholder":235},[176,1273,1275,1277,1280,1282,1284,1286],{"class":90,"line":1274},17,[176,1276,426],{"class":279},[176,1278,1279],{"class":228},"(load_workbook(",[176,1281,543],{"class":185},[176,1283,446],{"class":228},[176,1285,979],{"class":185},[176,1287,1288],{"class":228},"].value)\n",[176,1290,1292,1294,1297,1299,1301,1304,1306,1309,1311,1314,1316,1318,1321,1323,1325,1327,1329,1331],{"class":90,"line":1291},18,[176,1293,426],{"class":279},[176,1295,1296],{"class":228},"(pd.read_excel(",[176,1298,543],{"class":185},[176,1300,282],{"class":228},[176,1302,1303],{"class":548},"header",[176,1305,245],{"class":224},[176,1307,1308],{"class":279},"None",[176,1310,282],{"class":228},[176,1312,1313],{"class":548},"nrows",[176,1315,245],{"class":224},[176,1317,351],{"class":279},[176,1319,1320],{"class":228},").iloc[",[176,1322,319],{"class":279},[176,1324,287],{"class":228},[176,1326,52],{"class":279},[176,1328,282],{"class":228},[176,1330,351],{"class":279},[176,1332,1333],{"class":228},"]].tolist())\n",[10,1335,1336,1337,1340],{},"openpyxl shows the formula; pandas reads the stored results — \"3 of 6 steps done\" and 0.5 — because they were written with the formula. When someone ticks another box, Excel recalculates and the line updates to \"4 of 6\". The conditional format uses a formula anchored on column D, ",[19,1338,1339],{},"=$D4=TRUE",", so the whole row of a finished step turns grey and struck through; unticking the box restores it.",[30,1342,39,1348,39,1351,39,1354,39,1359,39,1365,39,1374,39,1378,39,1384,39,1388,39,1392,39,1396,39,1400,39,1404,39,1408,39,1412,39,1416,39,1418,39,1422,39,1424,39,1427,39,1429,39,1432,39,1434,39,1437,39,1440,39,1443,39,1445,39,1449,39,1451,39,1454,39,1456,39,1459,39,1461,39,1464,39,1467,39,1470,39,1472,39,1475,39,1477,39,1480,39,1482,39,1484,39,1486,39,1488,39,1491,39,1494,39,1496,39,1499,39,1501,39,1503,39,1505,39,1508,39,1513,39,1517,39,1520,39,1524,39,1526,39,1529,39,1531,39,1534,39,1536,39,1538,39,1540,39,1542,39,1545,39,1549,39,1551,39,1554,39,1556,39,1559,39,1561,39,1564,39,1566],{"viewBox":1343,"role":33,"ariaLabelledBy":1344,"xmlns":37,"style":1347},"166 0 427 256",[1345,1346],"cb-sheet-t","cb-sheet-d","width:100%;max-width:427px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[41,1349,1350],{"id":1345},"The close checklist with progress and struck-through rows",[45,1352,1353],{"id":1346},"The Close sheet. The title Month-end close September 2026, then 3 of 6 steps done and 50 percent. The table lists six steps with owner, due date and a Done checkbox. Bank reconciliation, AR aging reviewed and Payroll journal are ticked and shown grey with strikethrough. Accruals posted, Variance commentary and Pack sent to CFO are unticked.",[49,1355],{"x":1356,"y":52,"width":1357,"height":1358,"fill":55},"166","427","256",[78,1360,1364],{"x":1361,"y":1362,"style":1363},"380.0","31.0","font-size:14px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","close_checklist.xlsx — Close",[49,1366],{"x":1367,"y":1368,"width":1369,"height":1370,"rx":52,"fill":1371,"stroke":1372,"style":1373},"182.8","48.0","32.0","24.0","#e7ebef","var(--line,#cdd5e6)","stroke-width:1px",[49,1375],{"x":1376,"y":1368,"width":1377,"height":1370,"rx":52,"fill":1371,"stroke":1372,"style":1373},"214.8","176.2",[78,1379,1383],{"x":1380,"y":1381,"style":1382},"302.9","65.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[49,1385],{"x":1386,"y":1368,"width":1387,"height":1370,"rx":52,"fill":1371,"stroke":1372,"style":1373},"391.0","64.9",[78,1389,1391],{"x":1390,"y":1381,"style":1382},"423.4","B",[49,1393],{"x":1394,"y":1368,"width":1395,"height":1370,"rx":52,"fill":1371,"stroke":1372,"style":1373},"455.9","65.2",[78,1397,1399],{"x":1398,"y":1381,"style":1382},"488.5","C",[49,1401],{"x":1402,"y":1368,"width":1403,"height":1370,"rx":52,"fill":1371,"stroke":1372,"style":1373},"521.1","56.2",[78,1405,1407],{"x":1406,"y":1381,"style":1382},"549.1","D",[49,1409],{"x":1367,"y":1410,"width":1369,"height":1411,"rx":52,"fill":1371,"stroke":1372,"style":1373},"72.0","28.0",[78,1413,319],{"x":1414,"y":1415,"style":1382},"198.8","91.0",[49,1417],{"x":1376,"y":1410,"width":1377,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1419,1421],{"x":1380,"y":1415,"style":1420},"font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Step",[49,1423],{"x":1386,"y":1410,"width":1387,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1425,1426],{"x":1390,"y":1415,"style":1420},"Owner",[49,1428],{"x":1394,"y":1410,"width":1395,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1430,1431],{"x":1398,"y":1415,"style":1420},"Due",[49,1433],{"x":1402,"y":1410,"width":1403,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1435,1436],{"x":1406,"y":1415,"style":1420},"Done",[49,1438],{"x":1367,"y":1439,"width":1369,"height":1411,"rx":52,"fill":1371,"stroke":1372,"style":1373},"100.0",[78,1441,351],{"x":1414,"y":1442,"style":1382},"119.0",[49,1444],{"x":1376,"y":1439,"width":1377,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1446,1448],{"x":1380,"y":1442,"style":1447},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","~~Bank reconciliation~~",[49,1450],{"x":1386,"y":1439,"width":1387,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1452,1453],{"x":1390,"y":1442,"style":1447},"Ana",[49,1455],{"x":1394,"y":1439,"width":1395,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1457,1458],{"x":1398,"y":1442,"style":1447},"01 Oct",[49,1460],{"x":1402,"y":1439,"width":1403,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1462,1463],{"x":1406,"y":1442,"style":1447},"☑",[49,1465],{"x":1367,"y":1466,"width":1369,"height":1411,"rx":52,"fill":1371,"stroke":1372,"style":1373},"128.0",[78,1468,649],{"x":1414,"y":1469,"style":1382},"147.0",[49,1471],{"x":1376,"y":1466,"width":1377,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1473,1474],{"x":1380,"y":1469,"style":1447},"~~AR aging reviewed~~",[49,1476],{"x":1386,"y":1466,"width":1387,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1478,1479],{"x":1390,"y":1469,"style":1447},"Ben",[49,1481],{"x":1394,"y":1466,"width":1395,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1483,1458],{"x":1398,"y":1469,"style":1447},[49,1485],{"x":1402,"y":1466,"width":1403,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1487,1463],{"x":1406,"y":1469,"style":1447},[49,1489],{"x":1367,"y":1490,"width":1369,"height":1411,"rx":52,"fill":1371,"stroke":1372,"style":1373},"156.0",[78,1492,51],{"x":1414,"y":1493,"style":1382},"175.0",[49,1495],{"x":1376,"y":1490,"width":1377,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1497,1498],{"x":1380,"y":1493,"style":1447},"Accruals posted",[49,1500],{"x":1386,"y":1490,"width":1387,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1502,1453],{"x":1390,"y":1493,"style":1447},[49,1504],{"x":1394,"y":1490,"width":1395,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1506,1507],{"x":1398,"y":1493,"style":1447},"02 Oct",[49,1509],{"x":1402,"y":1490,"width":1403,"height":1411,"rx":52,"fill":1510,"stroke":1511,"style":1512},"#fdefd8","var(--gold,#b4740a)","stroke-width:1.5px",[78,1514,1516],{"x":1406,"y":1493,"style":1515},"font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","☐",[49,1518],{"x":1367,"y":1519,"width":1369,"height":1411,"rx":52,"fill":1371,"stroke":1372,"style":1373},"184.0",[78,1521,1523],{"x":1414,"y":1522,"style":1382},"203.0","5",[49,1525],{"x":1376,"y":1519,"width":1377,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1527,1528],{"x":1380,"y":1522,"style":1447},"~~Payroll journal~~",[49,1530],{"x":1386,"y":1519,"width":1387,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1532,1533],{"x":1390,"y":1522,"style":1447},"Cai",[49,1535],{"x":1394,"y":1519,"width":1395,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1537,1507],{"x":1398,"y":1522,"style":1447},[49,1539],{"x":1402,"y":1519,"width":1403,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1541,1463],{"x":1406,"y":1522,"style":1447},[49,1543],{"x":1367,"y":1544,"width":1369,"height":1411,"rx":52,"fill":1371,"stroke":1372,"style":1373},"212.0",[78,1546,1548],{"x":1414,"y":1547,"style":1382},"231.0","6",[49,1550],{"x":1376,"y":1544,"width":1377,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1552,1553],{"x":1380,"y":1547,"style":1447},"Variance commentary",[49,1555],{"x":1386,"y":1544,"width":1387,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1557,1558],{"x":1390,"y":1547,"style":1447},"Dee",[49,1560],{"x":1394,"y":1544,"width":1395,"height":1411,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1562,1563],{"x":1398,"y":1547,"style":1447},"05 Oct",[49,1565],{"x":1402,"y":1544,"width":1403,"height":1411,"rx":52,"fill":1510,"stroke":1511,"style":1512},[78,1567,1516],{"x":1406,"y":1547,"style":1515},[162,1569,1571],{"id":1570},"step-4-read-the-ticks-back","Step 4 — Read the ticks back",[10,1573,1574],{},"The point of a checklist is usually to collect the answers. Because checkboxes are plain booleans, reading them needs nothing special — pandas gives a boolean column:",[167,1576,1578],{"className":215,"code":1577,"language":217,"meta":172,"style":172},"back = pd.read_excel(\"close_checklist.xlsx\", skiprows=2)\nprint(back[[\"Step\", \"Owner\", \"Done\"]].to_string(index=False))\nprint(\"outstanding:\", back.loc[~back[\"Done\"], \"Owner\"].value_counts().to_dict())\n",[19,1579,1580,1602,1633],{"__ignoreMap":172},[176,1581,1582,1585,1587,1589,1591,1593,1596,1598,1600],{"class":90,"line":178},[176,1583,1584],{"class":228},"back ",[176,1586,245],{"class":224},[176,1588,513],{"class":228},[176,1590,543],{"class":185},[176,1592,282],{"class":228},[176,1594,1595],{"class":548},"skiprows",[176,1597,245],{"class":224},[176,1599,351],{"class":279},[176,1601,254],{"class":228},[176,1603,1604,1606,1609,1612,1614,1617,1619,1621,1624,1626,1628,1630],{"class":90,"line":232},[176,1605,426],{"class":279},[176,1607,1608],{"class":228},"(back[[",[176,1610,1611],{"class":185},"\"Step\"",[176,1613,282],{"class":228},[176,1615,1616],{"class":185},"\"Owner\"",[176,1618,282],{"class":228},[176,1620,295],{"class":185},[176,1622,1623],{"class":228},"]].to_string(",[176,1625,590],{"class":548},[176,1627,245],{"class":224},[176,1629,374],{"class":279},[176,1631,1632],{"class":228},"))\n",[176,1634,1635,1637,1640,1643,1646,1649,1652,1654,1656,1658],{"class":90,"line":239},[176,1636,426],{"class":279},[176,1638,1639],{"class":228},"(",[176,1641,1642],{"class":185},"\"outstanding:\"",[176,1644,1645],{"class":228},", back.loc[",[176,1647,1648],{"class":224},"~",[176,1650,1651],{"class":228},"back[",[176,1653,295],{"class":185},[176,1655,641],{"class":228},[176,1657,1616],{"class":185},[176,1659,1660],{"class":228},"].value_counts().to_dict())\n",[10,1662,1663,1664,1668],{},"The outstanding steps group by owner, ready for a reminder email. When collecting from many copies of the same checklist, read each one this way and concatenate; ",[24,1665,1667],{"href":1666},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fconsolidate-timesheets-from-many-workbooks\u002F","Consolidate Timesheets from Many Workbooks"," shows the pattern.",[162,1670,1672],{"id":1671},"let-people-tick-boxes-and-nothing-else","Let people tick boxes and nothing else",[10,1674,1675,1676,1678],{},"A shared checklist works best when the ticks are the only thing people can change: the steps, owners and formulas stay as they were written. Pass an unlocked format as the fourth argument of ",[19,1677,21],{}," and protect the sheet — every other cell is locked by default:",[167,1680,1682],{"className":215,"code":1681,"language":217,"meta":172,"style":172},"book = xlsxwriter.Workbook(\"close_protected.xlsx\")\nws = book.add_worksheet(\"Close\")\nunlocked = book.add_format({\"locked\": False})\nws.write_row(0, 0, [\"Step\", \"Owner\", \"Done\"], book.add_format({\"bold\": True}))\nfor i, r in enumerate(steps.itertuples(index=False), start=1):\n    ws.write(i, 0, r.Step)\n    ws.write(i, 1, r.Owner)\n    ws.insert_checkbox(i, 2, bool(r.Done), unlocked)\nws.set_column(0, 0, 24)\nws.protect()\nbook.close()\n\nsheet = load_workbook(\"close_protected.xlsx\").active\nprint(\"sheet protected:\", sheet.protection.sheet, \"| C2 locked:\", sheet[\"C2\"].protection.locked, \"| A2 locked:\", sheet[\"A2\"].protection.locked)\n",[19,1683,1684,1697,1710,1730,1763,1794,1804,1813,1827,1844,1849,1853,1857,1870],{"__ignoreMap":172},[176,1685,1686,1688,1690,1692,1695],{"class":90,"line":178},[176,1687,242],{"class":228},[176,1689,245],{"class":224},[176,1691,248],{"class":228},[176,1693,1694],{"class":185},"\"close_protected.xlsx\"",[176,1696,254],{"class":228},[176,1698,1699,1702,1704,1706,1708],{"class":90,"line":232},[176,1700,1701],{"class":228},"ws ",[176,1703,245],{"class":224},[176,1705,265],{"class":228},[176,1707,585],{"class":185},[176,1709,254],{"class":228},[176,1711,1712,1715,1717,1720,1723,1725,1727],{"class":90,"line":239},[176,1713,1714],{"class":228},"unlocked ",[176,1716,245],{"class":224},[176,1718,1719],{"class":228}," book.add_format({",[176,1721,1722],{"class":185},"\"locked\"",[176,1724,304],{"class":228},[176,1726,374],{"class":279},[176,1728,1729],{"class":228},"})\n",[176,1731,1732,1735,1737,1739,1741,1743,1745,1747,1749,1751,1753,1755,1757,1759,1761],{"class":90,"line":257},[176,1733,1734],{"class":228},"ws.write_row(",[176,1736,52],{"class":279},[176,1738,282],{"class":228},[176,1740,52],{"class":279},[176,1742,287],{"class":228},[176,1744,1611],{"class":185},[176,1746,282],{"class":228},[176,1748,1616],{"class":185},[176,1750,282],{"class":228},[176,1752,295],{"class":185},[176,1754,298],{"class":228},[176,1756,301],{"class":185},[176,1758,304],{"class":228},[176,1760,307],{"class":279},[176,1762,310],{"class":228},[176,1764,1765,1767,1770,1772,1774,1777,1779,1781,1783,1786,1788,1790,1792],{"class":90,"line":273},[176,1766,432],{"class":224},[176,1768,1769],{"class":228}," i, r ",[176,1771,438],{"class":224},[176,1773,633],{"class":279},[176,1775,1776],{"class":228},"(steps.itertuples(",[176,1778,590],{"class":548},[176,1780,245],{"class":224},[176,1782,374],{"class":279},[176,1784,1785],{"class":228},"), ",[176,1787,644],{"class":548},[176,1789,245],{"class":224},[176,1791,319],{"class":279},[176,1793,652],{"class":228},[176,1795,1796,1799,1801],{"class":90,"line":313},[176,1797,1798],{"class":228},"    ws.write(i, ",[176,1800,52],{"class":279},[176,1802,1803],{"class":228},", r.Step)\n",[176,1805,1806,1808,1810],{"class":90,"line":346},[176,1807,1798],{"class":228},[176,1809,319],{"class":279},[176,1811,1812],{"class":228},", r.Owner)\n",[176,1814,1815,1818,1820,1822,1824],{"class":90,"line":379},[176,1816,1817],{"class":228},"    ws.insert_checkbox(i, ",[176,1819,351],{"class":279},[176,1821,282],{"class":228},[176,1823,660],{"class":279},[176,1825,1826],{"class":228},"(r.Done), unlocked)\n",[176,1828,1829,1832,1834,1836,1838,1840,1842],{"class":90,"line":398},[176,1830,1831],{"class":228},"ws.set_column(",[176,1833,52],{"class":279},[176,1835,282],{"class":228},[176,1837,52],{"class":279},[176,1839,282],{"class":228},[176,1841,676],{"class":279},[176,1843,254],{"class":228},[176,1845,1846],{"class":90,"line":404},[176,1847,1848],{"class":228},"ws.protect()\n",[176,1850,1851],{"class":90,"line":409},[176,1852,401],{"class":228},[176,1854,1855],{"class":90,"line":423},[176,1856,236],{"emptyLinePlaceholder":235},[176,1858,1859,1861,1863,1865,1867],{"class":90,"line":709},[176,1860,260],{"class":228},[176,1862,245],{"class":224},[176,1864,441],{"class":228},[176,1866,1694],{"class":185},[176,1868,1869],{"class":228},").active\n",[176,1871,1872,1874,1876,1879,1882,1885,1888,1890,1893,1896,1898,1900],{"class":90,"line":744},[176,1873,426],{"class":279},[176,1875,1639],{"class":228},[176,1877,1878],{"class":185},"\"sheet protected:\"",[176,1880,1881],{"class":228},", sheet.protection.sheet, ",[176,1883,1884],{"class":185},"\"| C2 locked:\"",[176,1886,1887],{"class":228},", sheet[",[176,1889,1073],{"class":185},[176,1891,1892],{"class":228},"].protection.locked, ",[176,1894,1895],{"class":185},"\"| A2 locked:\"",[176,1897,1887],{"class":228},[176,1899,979],{"class":185},[176,1901,1902],{"class":228},"].protection.locked)\n",[10,1904,1905,1906,1910,1911,1914],{},"The checkbox cells remain clickable on a protected sheet, while the step names and owners cannot be edited. Protection without a password is a guard against accidents, not a security measure; ",[24,1907,1909],{"href":1908},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Flock-cells-and-protect-a-sheet-with-openpyxl\u002F","Lock Cells and Protect a Sheet with openpyxl"," explains the difference. Ticks also drive more than counts: ",[19,1912,1913],{},"=SUMIFS(E4:E9, D4:D9, TRUE)"," totals an amount column for ticked rows only, which turns a list of invoices with an \"approved\" checkbox into a running approved total.",[162,1916,1918],{"id":1917},"where-checkboxes-do-not-appear","Where checkboxes do not appear",[10,1920,1921],{},"Cell checkboxes are a new part of the file format, and support varies:",[30,1923,39,1928,39,1931,39,1934,39,1937,39,1941,39,1946,39,1952,39,1955,39,1959,39,1963,39,1968,39,1970,39,1974,39,1976,39,1983,39,1986,39,1990,39,1992,39,1996,39,1998,39,2003,39,2006,39,2010,39,2012,39,2015,39,2017,39,2022,39,2025,39,2029,39,2031,39,2035,39,2037,39,2042,39,2045,39,2049,39,2051,39,2055,39,2057],{"viewBox":1924,"role":33,"ariaLabelledBy":1925,"xmlns":37,"style":38},"4 0 752 242",[1926,1927],"cb-support-t","cb-support-d",[41,1929,1930],{"id":1926},"How a checkbox cell appears in different programs",[45,1932,1933],{"id":1927},"A table of programs. Current Microsoft 365 Excel shows a clickable checkbox. Older Excel versions show TRUE or FALSE. LibreOffice Calc shows TRUE or FALSE. pandas and openpyxl read True or False. Saving the workbook with openpyxl keeps the values but removes the checkbox formatting.",[49,1935],{"x":51,"y":52,"width":53,"height":1936,"fill":55},"242",[49,1938],{"x":58,"y":59,"width":1939,"height":1940,"rx":52,"fill":55,"stroke":1372,"style":1373},"188.6","40.0",[49,1942],{"x":1943,"y":59,"width":1944,"height":1940,"rx":52,"fill":63,"stroke":64,"style":1945},"208.6","265.7","stroke-width:1.2px",[78,1947,1951],{"x":1948,"y":1949,"style":1950},"341.5","41.0","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Shows",[49,1953],{"x":1954,"y":59,"width":1944,"height":1940,"rx":52,"fill":63,"stroke":64,"style":1945},"474.3",[78,1956,1958],{"x":1957,"y":1949,"style":1950},"607.2","Value kept",[49,1960],{"x":58,"y":1961,"width":1939,"height":1962,"rx":52,"fill":1371,"stroke":1372,"style":1373},"56.0","34.0",[78,1964,1967],{"x":1369,"y":1965,"style":1966},"78.0","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:start","Microsoft 365 Excel",[49,1969],{"x":1943,"y":1961,"width":1944,"height":1962,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1971,1973],{"x":1948,"y":1972,"style":87},"77.0","clickable checkbox",[49,1975],{"x":1954,"y":1961,"width":1944,"height":1962,"rx":52,"fill":55,"stroke":1372,"style":1373},[67,1977,1979],{"transform":1978},"translate(598.2,64.0) scale(0.750)",[71,1980],{"d":108,"fill":74,"stroke":1981,"style":1982},"var(--teal,#0f9488)","stroke-width:2.40px;stroke-linecap:round;stroke-linejoin:round",[49,1984],{"x":58,"y":1985,"width":1939,"height":1962,"rx":52,"fill":1371,"stroke":1372,"style":1373},"90.0",[78,1987,1989],{"x":1369,"y":1988,"style":1966},"112.0","Older Excel",[49,1991],{"x":1943,"y":1985,"width":1944,"height":1962,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,1993,1995],{"x":1948,"y":1994,"style":87},"111.0","TRUE \u002F FALSE",[49,1997],{"x":1954,"y":1985,"width":1944,"height":1962,"rx":52,"fill":55,"stroke":1372,"style":1373},[67,1999,2001],{"transform":2000},"translate(598.2,98.0) scale(0.750)",[71,2002],{"d":108,"fill":74,"stroke":1981,"style":1982},[49,2004],{"x":58,"y":2005,"width":1939,"height":1962,"rx":52,"fill":1371,"stroke":1372,"style":1373},"124.0",[78,2007,2009],{"x":1369,"y":2008,"style":1966},"146.0","LibreOffice Calc",[49,2011],{"x":1943,"y":2005,"width":1944,"height":1962,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,2013,1995],{"x":1948,"y":2014,"style":87},"145.0",[49,2016],{"x":1954,"y":2005,"width":1944,"height":1962,"rx":52,"fill":55,"stroke":1372,"style":1373},[67,2018,2020],{"transform":2019},"translate(598.2,132.0) scale(0.750)",[71,2021],{"d":108,"fill":74,"stroke":1981,"style":1982},[49,2023],{"x":58,"y":2024,"width":1939,"height":1962,"rx":52,"fill":1371,"stroke":1372,"style":1373},"158.0",[78,2026,2028],{"x":1369,"y":2027,"style":1966},"180.0","pandas \u002F openpyxl read",[49,2030],{"x":1943,"y":2024,"width":1944,"height":1962,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,2032,2034],{"x":1948,"y":2033,"style":87},"179.0","True \u002F False",[49,2036],{"x":1954,"y":2024,"width":1944,"height":1962,"rx":52,"fill":55,"stroke":1372,"style":1373},[67,2038,2040],{"transform":2039},"translate(598.2,166.0) scale(0.750)",[71,2041],{"d":108,"fill":74,"stroke":1981,"style":1982},[49,2043],{"x":58,"y":2044,"width":1939,"height":1962,"rx":52,"fill":1371,"stroke":1372,"style":1373},"192.0",[78,2046,2048],{"x":1369,"y":2047,"style":1966},"214.0","Saved again by openpyxl",[49,2050],{"x":1943,"y":2044,"width":1944,"height":1962,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,2052,2054],{"x":1948,"y":2053,"style":87},"213.0","TRUE \u002F FALSE only",[49,2056],{"x":1954,"y":2044,"width":1944,"height":1962,"rx":52,"fill":55,"stroke":1372,"style":1373},[78,2058,2059],{"x":1957,"y":2053,"style":87},"yes — boxes lost",[10,2061,2062,2063,2066,2067,2070,2071,2074],{},"Because the value is always kept, formulas and conditional formats behave the same everywhere; only the clickable box is missing. If the audience uses older Excel, add a data validation list of ",[19,2064,2065],{},"TRUE,FALSE"," to the column so people can still pick a value from a dropdown — xlsxwriter's ",[19,2068,2069],{},"data_validation"," with ",[19,2072,2073],{},"{\"validate\": \"list\", \"source\": [\"TRUE\", \"FALSE\"]}"," — and the checkboxes appear for those who can see them. Avoid post-processing the file with openpyxl: it reads the ticks fine, but saving drops the checkbox formatting.",[10,2076,2077,2078,2082],{},"A checkbox suits a genuine yes\u002Fno. When a step can be in more than two states — not started, in progress, done, not applicable — a dropdown of those words with a colour per value tells readers more than a box can, and works in every spreadsheet program; ",[24,2079,2081],{"href":2080},"\u002Fadvanced-data-transformation-and-cleaning\u002Fvalidating-excel-data-with-python\u002Fadd-dropdown-data-validation-to-excel-with-openpyxl\u002F","Add Dropdown Data Validation to Excel with openpyxl"," shows how to build one.",[162,2084,2086],{"id":2085},"common-pitfalls","Common pitfalls",[2088,2089,2090,2100,2110,2124,2134,2140],"ul",{},[2091,2092,2093,2096,2097,2099],"li",{},[14,2094,2095],{},"An old xlsxwriter."," ",[19,2098,21],{}," needs version 3.2.1 or later.",[2091,2101,2102,2105,2106,2109],{},[14,2103,2104],{},"NumPy booleans."," Convert with ",[19,2107,2108],{},"bool()"," before passing values in.",[2091,2111,2112,2115,2116,2119,2120,2123],{},[14,2113,2114],{},"Formulas showing 0."," Pass the known result as the ",[19,2117,2118],{},"value"," argument of ",[19,2121,2122],{},"write_formula",".",[2091,2125,2126,2129,2130,2133],{},[14,2127,2128],{},"Relative references in the conditional format."," Anchor the column (",[19,2131,2132],{},"$D4",") so each row checks its own box.",[2091,2135,2136,2139],{},[14,2137,2138],{},"Saving with openpyxl afterwards."," The checkbox formatting is removed; make xlsxwriter the last step.",[2091,2141,2142,2145],{},[14,2143,2144],{},"Assuming everyone sees boxes."," Older Excel and other programs show TRUE\u002FFALSE; label the column clearly.",[162,2147,2149],{"id":2148},"performance-notes","Performance notes",[10,2151,2152,2154],{},[19,2153,21],{}," writes one cell, so thousands of rows are no slower than writing booleans. The conditional format is a single rule over the whole range, not one per row.",[162,2156,2158],{"id":2157},"conclusion","Conclusion",[10,2160,2161,2162,2164,2165,2167],{},"Write checklist tables with pandas and replace the boolean column with ",[19,2163,21],{}," cells through the same xlsxwriter worksheet. Count ticks with ",[19,2166,789],{},", passing the result you already know so non-recalculating readers see it, and grey out finished rows with a conditional format anchored on the checkbox column. Read the answers back as ordinary booleans, and remember that only current Microsoft 365 shows the boxes — everywhere else sees TRUE and FALSE.",[162,2169,2171],{"id":2170},"frequently-asked-questions","Frequently asked questions",[10,2173,2174,2177],{},[14,2175,2176],{},"How do I add a checkbox to an Excel cell with Python?","\nWith xlsxwriter 3.2.1 or later, call worksheet.insert_checkbox(row, col, True or False). The cell stores a boolean and, in current Microsoft 365 versions of Excel, displays it as a checkbox that the reader can click.",[10,2179,2180,2183],{},[14,2181,2182],{},"Why do my checkboxes show as TRUE and FALSE?","\nCell checkboxes are a recent Microsoft 365 feature. Older Excel versions, LibreOffice and most other spreadsheet programs do not support it and show the underlying boolean instead. The value is the same, so formulas that use it still work.",[10,2185,2186,2189],{},[14,2187,2188],{},"How do I count ticked checkboxes in Excel?","\nA ticked checkbox is TRUE, so =COUNTIF(D2:D7,TRUE) counts them and =COUNTIF(D2:D7,TRUE)\u002FROWS(D2:D7) gives the share complete. When writing the formula with xlsxwriter, pass the expected result as the value argument so readers that do not recalculate see it.",[10,2191,2192,2195],{},[14,2193,2194],{},"Can openpyxl create or keep checkboxes?","\nopenpyxl reads the ticks as True and False, but it does not create checkboxes, and saving a workbook with openpyxl drops the checkbox formatting, leaving TRUE and FALSE values. Create checkbox workbooks with xlsxwriter as the final step.",[162,2197,2199],{"id":2198},"related","Related",[2088,2201,2202,2208,2215,2222],{},[2091,2203,2204,2205,2207],{},"Up one level: ",[24,2206,27],{"href":26}," — formatted reports from scratch.",[2091,2209,2210,2214],{},[24,2211,2213],{"href":2212},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fstore-formula-results-with-xlsxwriter\u002F","Store Formula Results with xlsxwriter"," — cached formula values.",[2091,2216,2217,2221],{},[24,2218,2220],{"href":2219},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fapply-conditional-formatting-with-xlsxwriter\u002F","Apply Conditional Formatting with xlsxwriter"," — formula-based rules.",[2091,2223,2224,2228],{},[24,2225,2227],{"href":2226},"\u002Fgetting-started-with-python-excel-automation\u002Freading-excel-files-with-pandas\u002Fread-boolean-columns-from-excel-with-pandas\u002F","Read Boolean Columns from Excel with pandas"," — reading the ticks.",[2230,2231,2232],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":172,"searchDepth":232,"depth":232,"links":2234},[2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246],{"id":164,"depth":232,"text":165},{"id":204,"depth":232,"text":205},{"id":477,"depth":232,"text":478},{"id":778,"depth":232,"text":779},{"id":1570,"depth":232,"text":1571},{"id":1671,"depth":232,"text":1672},{"id":1917,"depth":232,"text":1918},{"id":2085,"depth":232,"text":2086},{"id":2148,"depth":232,"text":2149},{"id":2157,"depth":232,"text":2158},{"id":2170,"depth":232,"text":2171},{"id":2198,"depth":232,"text":2199},"2026-09-25","Turn a column of TRUE\u002FFALSE values into clickable checkboxes — a month-end close checklist, a review sign-off column, a to-do list. Use xlsxwriter's insert_checkbox, count and percentage-complete formulas that show the right value before recalculation, strike through finished rows with conditional formatting, read the ticks back, and fall back gracefully where checkboxes are not supported.","md",[2251,2253,2255,2257],{"q":2176,"a":2252},"With xlsxwriter 3.2.1 or later, call worksheet.insert_checkbox(row, col, True or False). The cell stores a boolean and, in current Microsoft 365 versions of Excel, displays it as a checkbox that the reader can click.",{"q":2182,"a":2254},"Cell checkboxes are a recent Microsoft 365 feature. Older Excel versions, LibreOffice and most other spreadsheet programs do not support it and show the underlying boolean instead. The value is the same, so formulas that use it still work.",{"q":2188,"a":2256},"A ticked checkbox is TRUE, so =COUNTIF(D2:D7,TRUE) counts them and =COUNTIF(D2:D7,TRUE)\u002FROWS(D2:D7) gives the share complete. When writing the formula with xlsxwriter, pass the expected result as the value argument so readers that do not recalculate see it.",{"q":2194,"a":2258},"openpyxl reads the ticks as True and False, but it does not create checkboxes, and saving a workbook with openpyxl drops the checkbox formatting, leaving TRUE and FALSE values. Create checkbox workbooks with xlsxwriter as the final step.","insert checkboxes with xlsxwriter",null,{"breadcrumb":2262},[2263,2265,2268],{"name":2264,"item":1143},"Home",{"name":2266,"item":2267},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":27,"item":26},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Finsert-checkboxes-with-xlsxwriter",{"title":2271,"description":2272},"Add Checkboxes to Excel Cells with Python xlsxwriter","Insert Excel cell checkboxes with xlsxwriter insert_checkbox: boolean cells shown as checkboxes in Microsoft 365, writing them from a DataFrame, COUNTIF progress formulas with cached values, strikethrough for checked rows, reading ticks with pandas and openpyxl, and TRUE\u002FFALSE fallbacks.","insert-checkboxes-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Finsert-checkboxes-with-xlsxwriter\u002Findex",[2276,2277],"xlsxwriter","report-layouts","how-to","7tg56zThcnI4-02aaA9Yylq8R7aW6EOZEo3CxK93gBQ",[2281,2285],{"title":2282,"path":2283,"stem":2284,"children":-1},"Freeze Panes and Set Zoom with XlsxWriter","\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Ffreeze-panes-and-set-zoom-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Ffreeze-panes-and-set-zoom-with-xlsxwriter\u002Findex",{"title":2286,"path":2287,"stem":2288,"children":-1},"Label Chart Points from Cell Values with XlsxWriter","\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Flabel-chart-points-from-cell-values-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Flabel-chart-points-from-cell-values-with-xlsxwriter\u002Findex",[2290,2292],{"path":2291,"title":27},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter",{"path":2293,"title":2266},"\u002Fformatting-and-charting-excel-reports-with-python",[],[2296,2300,2303,2306,2307,2310],{"path":2297,"title":2298,"kind":2299},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-budget-vs-actual-variance-report","Build a Budget vs Actual Variance Report in Excel with Python","compare",{"path":2301,"title":2302,"kind":2278},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fcombine-chart-types-and-chartsheets-with-xlsxwriter","Combine Chart Types and Chartsheets with XlsxWriter",{"path":2304,"title":2305,"kind":2278},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fdefine-names-and-protect-sheets-with-xlsxwriter","Define Names and Protect Sheets with XlsxWriter",{"path":2283,"title":2282,"kind":2278},{"path":2308,"title":2309,"kind":2278},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fset-print-options-headers-and-footers-with-xlsxwriter","Set Print Options, Headers and Footers with XlsxWriter",{"path":2311,"title":2312,"kind":2278},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-an-excel-table-with-formula-columns-using-xlsxwriter","Write an Excel Table with Formula Columns Using XlsxWriter",1790972108597]