[{"data":1,"prerenderedAt":2267},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-a-chart-to-an-excel-file-with-xlsxwriter":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-a-chart-to-an-excel-file-with-xlsxwriter":2259},{"id":4,"title":5,"body":6,"dateModified":2228,"datePublished":2228,"description":2229,"extension":2230,"faq":2231,"meta":2240,"navigation":260,"path":2251,"seo":2252,"slug":2255,"stem":2256,"type":2257,"__hash__":2258},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-a-chart-to-an-excel-file-with-xlsxwriter\u002Findex.md","Add a Chart to an Excel File with xlsxwriter",{"type":7,"value":8,"toc":2215},"minimark",[9,13,22,181,186,214,217,221,224,736,742,746,1111,1134,1148,1152,1155,1588,1602,1752,1756,1762,1837,1880,1887,1891,1894,1935,1947,1951,2091,2095,2103,2111,2115,2118,2122,2132,2144,2150,2162,2166,2169,2178,2181,2211],[10,11,12],"p",{},"An Excel chart written by xlsxwriter is a real chart object: it references cells, recalculates when someone edits them, and can be restyled by hand afterwards. That is the difference between it and a rendered image pasted into a sheet — and it is why a chart built from Python is worth the extra ten lines over exporting a picture.",[10,14,15,16,21],{},"This guide, part of ",[17,18,20],"a",{"href":19},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002F","Building Excel Reports with xlsxwriter",", covers series ranges that follow the data, axis and label formatting that make the chart readable, and the combined chart with a secondary axis that most monthly reports eventually need.",[23,24,32,33,32,37,32,41,32,48,32,55,32,62,32,68,32,72,32,76,32,81,32,86,32,90,32,93,32,96,32,100,32,102,32,105,32,108,32,112,32,114,32,117,32,126,32,131,32,136,32,140,32,144,32,148,32,156,32,162,32,165,32,169,32,172,32,175],"svg",{"viewBox":25,"role":26,"ariaLabelledBy":27,"xmlns":30,"style":31},"0 0 740 250","img",[28,29],"xc-anatomy-t","xc-anatomy-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:740px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[34,35,36],"title",{"id":28},"How a chart series points back at the worksheet",[38,39,40],"desc",{"id":29},"A series has three parts. Categories point at the label column, values point at the number column, and the name is a single header cell. Each is given as a list of sheet name, first row, first column, last row and last column, computed from the number of rows written rather than typed.",[42,43],"rect",{"x":44,"y":44,"width":45,"height":46,"fill":47},"0","740","250","#ffffff",[49,50,54],"text",{"x":51,"y":52,"style":53},"150","32","font-size:12.5px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","the worksheet",[42,56],{"x":57,"y":58,"width":59,"height":60,"fill":61},"30","46","100","26","#1f4e78",[49,63,67],{"x":64,"y":65,"style":66},"80","64","font-size:11px;font-weight:700;fill:#ffffff;text-anchor:middle","Region",[42,69],{"x":70,"y":58,"width":71,"height":60,"fill":61},"130","110",[49,73,75],{"x":74,"y":65,"style":66},"185","Amount",[42,77],{"x":57,"y":78,"width":59,"height":60,"fill":79,"stroke":80},"72","#ebebfd","var(--brand,#5b5cf0)",[49,82,85],{"x":64,"y":83,"style":84},"90","font-size:11px;fill:var(--text,#172033);text-anchor:middle","South",[42,87],{"x":70,"y":78,"width":71,"height":60,"fill":88,"stroke":89},"#d9f4f1","var(--teal,#0f9488)",[49,91,92],{"x":74,"y":83,"style":84},"274.75",[42,94],{"x":57,"y":95,"width":59,"height":60,"fill":79,"stroke":80},"98",[49,97,99],{"x":64,"y":98,"style":84},"116","North",[42,101],{"x":70,"y":95,"width":71,"height":60,"fill":88,"stroke":89},[49,103,104],{"x":74,"y":98,"style":84},"150.25",[42,106],{"x":57,"y":107,"width":59,"height":60,"fill":79,"stroke":80},"124",[49,109,111],{"x":64,"y":110,"style":84},"142","East",[42,113],{"x":70,"y":107,"width":71,"height":60,"fill":88,"stroke":89},[49,115,116],{"x":74,"y":110,"style":84},"75.00",[118,119],"line",{"x1":120,"y1":121,"x2":122,"y2":123,"stroke":124,"style":125},"244","59","330","82","var(--gold,#b4740a)","stroke-width:1.5px",[127,128],"polygon",{"points":129,"fill":130},"334,84 322,79 324,89","#8a5808",[118,132],{"x1":133,"y1":134,"x2":122,"y2":135,"stroke":80,"style":125},"134","154","132",[127,137],{"points":138,"fill":139},"334,131 322,128 324,138","#5b5cf0",[118,141],{"x1":120,"y1":142,"x2":122,"y2":143,"stroke":89,"style":125},"140","178",[127,145],{"points":146,"fill":147},"334,180 322,175 324,185","#0f766e",[42,149],{"x":150,"y":65,"width":151,"height":152,"rx":153,"fill":154,"stroke":124,"style":155},"338","386","40","8","#fdefd8","stroke-width:2px",[49,157,161],{"x":158,"y":159,"style":160},"358","89","font-size:11.5px;fill:var(--text,#172033)","\"name\": [\"Summary\", 0, 1] — one header cell",[42,163],{"x":150,"y":164,"width":151,"height":152,"rx":153,"fill":79,"stroke":80,"style":155},"112",[49,166,168],{"x":158,"y":167,"style":160},"137","\"categories\": [\"Summary\", 1, 0, n, 0] — the labels",[42,170],{"x":150,"y":171,"width":151,"height":152,"rx":153,"fill":88,"stroke":89,"style":155},"160",[49,173,174],{"x":158,"y":74,"style":160},"\"values\": [\"Summary\", 1, 1, n, 1] — the numbers",[49,176,180],{"x":177,"y":178,"style":179},"531","228","font-size:11px;fill:var(--muted,#5b6780);text-anchor:middle","n comes from len(df), never from a typed row number",[182,183,185],"h2",{"id":184},"prerequisites","Prerequisites",[187,188,193],"pre",{"className":189,"code":190,"language":191,"meta":192,"style":192},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install xlsxwriter pandas\n","bash","",[194,195,196],"code",{"__ignoreMap":192},[197,198,200,204,208,211],"span",{"class":118,"line":199},1,[197,201,203],{"class":202},"sMTad","pip",[197,205,207],{"class":206},"srMev"," install",[197,209,210],{"class":206}," xlsxwriter",[197,212,213],{"class":206}," pandas\n",[10,215,216],{},"No Excel installation is needed — xlsxwriter writes the chart definition into the file directly, and Excel or LibreOffice renders it on open.",[182,218,220],{"id":219},"step-1-write-the-data-the-chart-will-reference","Step 1: Write the data the chart will reference",[10,222,223],{},"A chart plots cells, so the data has to exist in the sheet first:",[187,225,229],{"className":226,"code":227,"language":228,"meta":192,"style":192},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\nimport xlsxwriter\n\ndf = pd.DataFrame({\n    \"month\":  [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\"],\n    \"amount\": [412.0, 388.5, 501.25, 466.0, 590.75, 623.4],\n    \"margin\": [0.31, 0.29, 0.34, 0.33, 0.36, 0.38],\n})\n\nwb = xlsxwriter.Workbook(\"charted.xlsx\")\nws = wb.add_worksheet(\"Summary\")\n\nheader = wb.add_format({\"bold\": True, \"bg_color\": \"#1F4E78\",\n                        \"font_color\": \"white\", \"border\": 1})\nmoney = wb.add_format({\"num_format\": '#,##0.00', \"border\": 1})\npct = wb.add_format({\"num_format\": \"0.0%\", \"border\": 1})\n\nws.write_row(0, 0, [\"Month\", \"Amount\", \"Margin\"], header)\nfor i, row in enumerate(df.itertuples(index=False), start=1):\n    ws.write_string(i, 0, row.month)\n    ws.write_number(i, 1, row.amount, money)\n    ws.write_number(i, 2, row.margin, pct)\n\nws.set_column(\"A:A\", 12)\nws.set_column(\"B:B\", 14)\nws.set_column(\"C:C\", 12)\n\nLAST = len(df)          # zero-based index of the last data row\n","python",[194,230,231,247,255,262,274,315,355,393,399,404,421,437,442,475,498,526,553,558,589,629,640,651,662,667,683,698,712,717],{"__ignoreMap":192},[197,232,233,237,241,244],{"class":118,"line":199},[197,234,236],{"class":235},"s-kum","import",[197,238,240],{"class":239},"skGVy"," pandas ",[197,242,243],{"class":235},"as",[197,245,246],{"class":239}," pd\n",[197,248,250,252],{"class":118,"line":249},2,[197,251,236],{"class":235},[197,253,254],{"class":239}," xlsxwriter\n",[197,256,258],{"class":118,"line":257},3,[197,259,261],{"emptyLinePlaceholder":260},true,"\n",[197,263,265,268,271],{"class":118,"line":264},4,[197,266,267],{"class":239},"df ",[197,269,270],{"class":235},"=",[197,272,273],{"class":239}," pd.DataFrame({\n",[197,275,277,280,283,286,289,292,294,297,299,302,304,307,309,312],{"class":118,"line":276},5,[197,278,279],{"class":206},"    \"month\"",[197,281,282],{"class":239},":  [",[197,284,285],{"class":206},"\"Jan\"",[197,287,288],{"class":239},", ",[197,290,291],{"class":206},"\"Feb\"",[197,293,288],{"class":239},[197,295,296],{"class":206},"\"Mar\"",[197,298,288],{"class":239},[197,300,301],{"class":206},"\"Apr\"",[197,303,288],{"class":239},[197,305,306],{"class":206},"\"May\"",[197,308,288],{"class":239},[197,310,311],{"class":206},"\"Jun\"",[197,313,314],{"class":239},"],\n",[197,316,318,321,324,328,330,333,335,338,340,343,345,348,350,353],{"class":118,"line":317},6,[197,319,320],{"class":206},"    \"amount\"",[197,322,323],{"class":239},": [",[197,325,327],{"class":326},"sP0c6","412.0",[197,329,288],{"class":239},[197,331,332],{"class":326},"388.5",[197,334,288],{"class":239},[197,336,337],{"class":326},"501.25",[197,339,288],{"class":239},[197,341,342],{"class":326},"466.0",[197,344,288],{"class":239},[197,346,347],{"class":326},"590.75",[197,349,288],{"class":239},[197,351,352],{"class":326},"623.4",[197,354,314],{"class":239},[197,356,358,361,363,366,368,371,373,376,378,381,383,386,388,391],{"class":118,"line":357},7,[197,359,360],{"class":206},"    \"margin\"",[197,362,323],{"class":239},[197,364,365],{"class":326},"0.31",[197,367,288],{"class":239},[197,369,370],{"class":326},"0.29",[197,372,288],{"class":239},[197,374,375],{"class":326},"0.34",[197,377,288],{"class":239},[197,379,380],{"class":326},"0.33",[197,382,288],{"class":239},[197,384,385],{"class":326},"0.36",[197,387,288],{"class":239},[197,389,390],{"class":326},"0.38",[197,392,314],{"class":239},[197,394,396],{"class":118,"line":395},8,[197,397,398],{"class":239},"})\n",[197,400,402],{"class":118,"line":401},9,[197,403,261],{"emptyLinePlaceholder":260},[197,405,407,410,412,415,418],{"class":118,"line":406},10,[197,408,409],{"class":239},"wb ",[197,411,270],{"class":235},[197,413,414],{"class":239}," xlsxwriter.Workbook(",[197,416,417],{"class":206},"\"charted.xlsx\"",[197,419,420],{"class":239},")\n",[197,422,424,427,429,432,435],{"class":118,"line":423},11,[197,425,426],{"class":239},"ws ",[197,428,270],{"class":235},[197,430,431],{"class":239}," wb.add_worksheet(",[197,433,434],{"class":206},"\"Summary\"",[197,436,420],{"class":239},[197,438,440],{"class":118,"line":439},12,[197,441,261],{"emptyLinePlaceholder":260},[197,443,445,448,450,453,456,459,462,464,467,469,472],{"class":118,"line":444},13,[197,446,447],{"class":239},"header ",[197,449,270],{"class":235},[197,451,452],{"class":239}," wb.add_format({",[197,454,455],{"class":206},"\"bold\"",[197,457,458],{"class":239},": ",[197,460,461],{"class":326},"True",[197,463,288],{"class":239},[197,465,466],{"class":206},"\"bg_color\"",[197,468,458],{"class":239},[197,470,471],{"class":206},"\"#1F4E78\"",[197,473,474],{"class":239},",\n",[197,476,478,481,483,486,488,491,493,496],{"class":118,"line":477},14,[197,479,480],{"class":206},"                        \"font_color\"",[197,482,458],{"class":239},[197,484,485],{"class":206},"\"white\"",[197,487,288],{"class":239},[197,489,490],{"class":206},"\"border\"",[197,492,458],{"class":239},[197,494,495],{"class":326},"1",[197,497,398],{"class":239},[197,499,501,504,506,508,511,513,516,518,520,522,524],{"class":118,"line":500},15,[197,502,503],{"class":239},"money ",[197,505,270],{"class":235},[197,507,452],{"class":239},[197,509,510],{"class":206},"\"num_format\"",[197,512,458],{"class":239},[197,514,515],{"class":206},"'#,##0.00'",[197,517,288],{"class":239},[197,519,490],{"class":206},[197,521,458],{"class":239},[197,523,495],{"class":326},[197,525,398],{"class":239},[197,527,529,532,534,536,538,540,543,545,547,549,551],{"class":118,"line":528},16,[197,530,531],{"class":239},"pct ",[197,533,270],{"class":235},[197,535,452],{"class":239},[197,537,510],{"class":206},[197,539,458],{"class":239},[197,541,542],{"class":206},"\"0.0%\"",[197,544,288],{"class":239},[197,546,490],{"class":206},[197,548,458],{"class":239},[197,550,495],{"class":326},[197,552,398],{"class":239},[197,554,556],{"class":118,"line":555},17,[197,557,261],{"emptyLinePlaceholder":260},[197,559,561,564,566,568,570,573,576,578,581,583,586],{"class":118,"line":560},18,[197,562,563],{"class":239},"ws.write_row(",[197,565,44],{"class":326},[197,567,288],{"class":239},[197,569,44],{"class":326},[197,571,572],{"class":239},", [",[197,574,575],{"class":206},"\"Month\"",[197,577,288],{"class":239},[197,579,580],{"class":206},"\"Amount\"",[197,582,288],{"class":239},[197,584,585],{"class":206},"\"Margin\"",[197,587,588],{"class":239},"], header)\n",[197,590,592,595,598,601,604,607,611,613,616,619,622,624,626],{"class":118,"line":591},19,[197,593,594],{"class":235},"for",[197,596,597],{"class":239}," i, row ",[197,599,600],{"class":235},"in",[197,602,603],{"class":326}," enumerate",[197,605,606],{"class":239},"(df.itertuples(",[197,608,610],{"class":609},"sa561","index",[197,612,270],{"class":235},[197,614,615],{"class":326},"False",[197,617,618],{"class":239},"), ",[197,620,621],{"class":609},"start",[197,623,270],{"class":235},[197,625,495],{"class":326},[197,627,628],{"class":239},"):\n",[197,630,632,635,637],{"class":118,"line":631},20,[197,633,634],{"class":239},"    ws.write_string(i, ",[197,636,44],{"class":326},[197,638,639],{"class":239},", row.month)\n",[197,641,643,646,648],{"class":118,"line":642},21,[197,644,645],{"class":239},"    ws.write_number(i, ",[197,647,495],{"class":326},[197,649,650],{"class":239},", row.amount, money)\n",[197,652,654,656,659],{"class":118,"line":653},22,[197,655,645],{"class":239},[197,657,658],{"class":326},"2",[197,660,661],{"class":239},", row.margin, pct)\n",[197,663,665],{"class":118,"line":664},23,[197,666,261],{"emptyLinePlaceholder":260},[197,668,670,673,676,678,681],{"class":118,"line":669},24,[197,671,672],{"class":239},"ws.set_column(",[197,674,675],{"class":206},"\"A:A\"",[197,677,288],{"class":239},[197,679,680],{"class":326},"12",[197,682,420],{"class":239},[197,684,686,688,691,693,696],{"class":118,"line":685},25,[197,687,672],{"class":239},[197,689,690],{"class":206},"\"B:B\"",[197,692,288],{"class":239},[197,694,695],{"class":326},"14",[197,697,420],{"class":239},[197,699,701,703,706,708,710],{"class":118,"line":700},26,[197,702,672],{"class":239},[197,704,705],{"class":206},"\"C:C\"",[197,707,288],{"class":239},[197,709,680],{"class":326},[197,711,420],{"class":239},[197,713,715],{"class":118,"line":714},27,[197,716,261],{"emptyLinePlaceholder":260},[197,718,720,723,726,729,732],{"class":118,"line":719},28,[197,721,722],{"class":326},"LAST",[197,724,725],{"class":235}," =",[197,727,728],{"class":326}," len",[197,730,731],{"class":239},"(df)          ",[197,733,735],{"class":734},"s-wDw","# zero-based index of the last data row\n",[10,737,738,739,741],{},"Keeping ",[194,740,722],{}," as a variable is the single habit that prevents most chart bugs. Every range below is expressed relative to it, so a month added to the DataFrame extends the chart automatically.",[182,743,745],{"id":744},"step-2-a-column-chart-with-readable-axes","Step 2: A column chart with readable axes",[187,747,749],{"className":226,"code":748,"language":228,"meta":192,"style":192},"chart = wb.add_chart({\"type\": \"column\"})\nchart.add_series({\n    \"name\":       [\"Summary\", 0, 1],\n    \"categories\": [\"Summary\", 1, 0, LAST, 0],\n    \"values\":     [\"Summary\", 1, 1, LAST, 1],\n    \"fill\":       {\"color\": \"#5B5CF0\"},\n    \"gap\":        40,\n    \"data_labels\": {\"value\": True, \"num_format\": \"#,##0\",\n                    \"font\": {\"size\": 9, \"color\": \"#5B6780\"}},\n})\nchart.set_title({\"name\": \"Monthly amount\",\n                 \"name_font\": {\"size\": 13, \"bold\": True}})\nchart.set_x_axis({\"name\": \"Month\", \"num_font\": {\"size\": 10}})\nchart.set_y_axis({\"name\": \"Amount\", \"num_format\": '#,##0',\n                  \"major_gridlines\": {\"visible\": True,\n                                      \"line\": {\"color\": \"#E4E8F2\"}}})\nchart.set_legend({\"none\": True})\nchart.set_size({\"width\": 640, \"height\": 340})\nws.insert_chart(\"E2\", chart)\n",[194,750,751,771,776,796,823,851,870,882,908,935,939,954,979,1006,1028,1044,1061,1075,1100],{"__ignoreMap":192},[197,752,753,756,758,761,764,766,769],{"class":118,"line":199},[197,754,755],{"class":239},"chart ",[197,757,270],{"class":235},[197,759,760],{"class":239}," wb.add_chart({",[197,762,763],{"class":206},"\"type\"",[197,765,458],{"class":239},[197,767,768],{"class":206},"\"column\"",[197,770,398],{"class":239},[197,772,773],{"class":118,"line":249},[197,774,775],{"class":239},"chart.add_series({\n",[197,777,778,781,784,786,788,790,792,794],{"class":118,"line":257},[197,779,780],{"class":206},"    \"name\"",[197,782,783],{"class":239},":       [",[197,785,434],{"class":206},[197,787,288],{"class":239},[197,789,44],{"class":326},[197,791,288],{"class":239},[197,793,495],{"class":326},[197,795,314],{"class":239},[197,797,798,801,803,805,807,809,811,813,815,817,819,821],{"class":118,"line":264},[197,799,800],{"class":206},"    \"categories\"",[197,802,323],{"class":239},[197,804,434],{"class":206},[197,806,288],{"class":239},[197,808,495],{"class":326},[197,810,288],{"class":239},[197,812,44],{"class":326},[197,814,288],{"class":239},[197,816,722],{"class":326},[197,818,288],{"class":239},[197,820,44],{"class":326},[197,822,314],{"class":239},[197,824,825,828,831,833,835,837,839,841,843,845,847,849],{"class":118,"line":276},[197,826,827],{"class":206},"    \"values\"",[197,829,830],{"class":239},":     [",[197,832,434],{"class":206},[197,834,288],{"class":239},[197,836,495],{"class":326},[197,838,288],{"class":239},[197,840,495],{"class":326},[197,842,288],{"class":239},[197,844,722],{"class":326},[197,846,288],{"class":239},[197,848,495],{"class":326},[197,850,314],{"class":239},[197,852,853,856,859,862,864,867],{"class":118,"line":317},[197,854,855],{"class":206},"    \"fill\"",[197,857,858],{"class":239},":       {",[197,860,861],{"class":206},"\"color\"",[197,863,458],{"class":239},[197,865,866],{"class":206},"\"#5B5CF0\"",[197,868,869],{"class":239},"},\n",[197,871,872,875,878,880],{"class":118,"line":357},[197,873,874],{"class":206},"    \"gap\"",[197,876,877],{"class":239},":        ",[197,879,152],{"class":326},[197,881,474],{"class":239},[197,883,884,887,890,893,895,897,899,901,903,906],{"class":118,"line":395},[197,885,886],{"class":206},"    \"data_labels\"",[197,888,889],{"class":239},": {",[197,891,892],{"class":206},"\"value\"",[197,894,458],{"class":239},[197,896,461],{"class":326},[197,898,288],{"class":239},[197,900,510],{"class":206},[197,902,458],{"class":239},[197,904,905],{"class":206},"\"#,##0\"",[197,907,474],{"class":239},[197,909,910,913,915,918,920,923,925,927,929,932],{"class":118,"line":401},[197,911,912],{"class":206},"                    \"font\"",[197,914,889],{"class":239},[197,916,917],{"class":206},"\"size\"",[197,919,458],{"class":239},[197,921,922],{"class":326},"9",[197,924,288],{"class":239},[197,926,861],{"class":206},[197,928,458],{"class":239},[197,930,931],{"class":206},"\"#5B6780\"",[197,933,934],{"class":239},"}},\n",[197,936,937],{"class":118,"line":406},[197,938,398],{"class":239},[197,940,941,944,947,949,952],{"class":118,"line":423},[197,942,943],{"class":239},"chart.set_title({",[197,945,946],{"class":206},"\"name\"",[197,948,458],{"class":239},[197,950,951],{"class":206},"\"Monthly amount\"",[197,953,474],{"class":239},[197,955,956,959,961,963,965,968,970,972,974,976],{"class":118,"line":439},[197,957,958],{"class":206},"                 \"name_font\"",[197,960,889],{"class":239},[197,962,917],{"class":206},[197,964,458],{"class":239},[197,966,967],{"class":326},"13",[197,969,288],{"class":239},[197,971,455],{"class":206},[197,973,458],{"class":239},[197,975,461],{"class":326},[197,977,978],{"class":239},"}})\n",[197,980,981,984,986,988,990,992,995,997,999,1001,1004],{"class":118,"line":444},[197,982,983],{"class":239},"chart.set_x_axis({",[197,985,946],{"class":206},[197,987,458],{"class":239},[197,989,575],{"class":206},[197,991,288],{"class":239},[197,993,994],{"class":206},"\"num_font\"",[197,996,889],{"class":239},[197,998,917],{"class":206},[197,1000,458],{"class":239},[197,1002,1003],{"class":326},"10",[197,1005,978],{"class":239},[197,1007,1008,1011,1013,1015,1017,1019,1021,1023,1026],{"class":118,"line":477},[197,1009,1010],{"class":239},"chart.set_y_axis({",[197,1012,946],{"class":206},[197,1014,458],{"class":239},[197,1016,580],{"class":206},[197,1018,288],{"class":239},[197,1020,510],{"class":206},[197,1022,458],{"class":239},[197,1024,1025],{"class":206},"'#,##0'",[197,1027,474],{"class":239},[197,1029,1030,1033,1035,1038,1040,1042],{"class":118,"line":500},[197,1031,1032],{"class":206},"                  \"major_gridlines\"",[197,1034,889],{"class":239},[197,1036,1037],{"class":206},"\"visible\"",[197,1039,458],{"class":239},[197,1041,461],{"class":326},[197,1043,474],{"class":239},[197,1045,1046,1049,1051,1053,1055,1058],{"class":118,"line":528},[197,1047,1048],{"class":206},"                                      \"line\"",[197,1050,889],{"class":239},[197,1052,861],{"class":206},[197,1054,458],{"class":239},[197,1056,1057],{"class":206},"\"#E4E8F2\"",[197,1059,1060],{"class":239},"}}})\n",[197,1062,1063,1066,1069,1071,1073],{"class":118,"line":555},[197,1064,1065],{"class":239},"chart.set_legend({",[197,1067,1068],{"class":206},"\"none\"",[197,1070,458],{"class":239},[197,1072,461],{"class":326},[197,1074,398],{"class":239},[197,1076,1077,1080,1083,1085,1088,1090,1093,1095,1098],{"class":118,"line":560},[197,1078,1079],{"class":239},"chart.set_size({",[197,1081,1082],{"class":206},"\"width\"",[197,1084,458],{"class":239},[197,1086,1087],{"class":326},"640",[197,1089,288],{"class":239},[197,1091,1092],{"class":206},"\"height\"",[197,1094,458],{"class":239},[197,1096,1097],{"class":326},"340",[197,1099,398],{"class":239},[197,1101,1102,1105,1108],{"class":118,"line":591},[197,1103,1104],{"class":239},"ws.insert_chart(",[197,1106,1107],{"class":206},"\"E2\"",[197,1109,1110],{"class":239},", chart)\n",[10,1112,1113,1114,1117,1118,1121,1122,1125,1126,1129,1130,1133],{},"Three of those settings do most of the readability work. ",[194,1115,1116],{},"num_format"," on the y-axis stops a currency axis showing ",[194,1119,1120],{},"500000"," instead of ",[194,1123,1124],{},"500,000",". ",[194,1127,1128],{},"set_legend({\"none\": True})"," removes the legend for a single-series chart, where it explains nothing and takes a fifth of the width. And ",[194,1131,1132],{},"data_labels"," puts the value on the bar, which for six categories is more useful than making the reader trace back to the axis.",[10,1135,1136,1139,1140,1143,1144,1147],{},[194,1137,1138],{},"set_size"," takes pixels; ",[194,1141,1142],{},"insert_chart"," also accepts ",[194,1145,1146],{},"{\"x_scale\": 1.5, \"y_scale\": 1.2}"," if you would rather scale than specify. Anchoring at a cell well to the right of the data means the chart does not cover the table when someone widens a column.",[182,1149,1151],{"id":1150},"step-3-combine-two-series-with-different-units","Step 3: Combine two series with different units",[10,1153,1154],{},"Amount in currency and margin in percent cannot share an axis meaningfully. The idiomatic answer is two chart objects combined, with the second on a secondary axis:",[187,1156,1158],{"className":226,"code":1157,"language":228,"meta":192,"style":192},"column = wb.add_chart({\"type\": \"column\"})\ncolumn.add_series({\n    \"name\":       [\"Summary\", 0, 1],\n    \"categories\": [\"Summary\", 1, 0, LAST, 0],\n    \"values\":     [\"Summary\", 1, 1, LAST, 1],\n    \"fill\":       {\"color\": \"#5B5CF0\"},\n})\n\nline = wb.add_chart({\"type\": \"line\"})\nline.add_series({\n    \"name\":       [\"Summary\", 0, 2],\n    \"categories\": [\"Summary\", 1, 0, LAST, 0],\n    \"values\":     [\"Summary\", 1, 2, LAST, 2],\n    \"line\":       {\"color\": \"#0F766E\", \"width\": 2.25},\n    \"marker\":     {\"type\": \"circle\", \"size\": 6,\n                   \"fill\": {\"color\": \"#0F766E\"}},\n    \"y2_axis\":    True,                       # plot against the right-hand axis\n})\n\ncolumn.combine(line)\ncolumn.set_title({\"name\": \"Amount and margin by month\"})\ncolumn.set_y_axis({\"name\": \"Amount\", \"num_format\": '#,##0'})\ncolumn.set_y2_axis({\"name\": \"Margin\", \"num_format\": \"0%\",\n                    \"min\": 0, \"max\": 0.5})\ncolumn.set_legend({\"position\": \"bottom\"})\ncolumn.set_size({\"width\": 720, \"height\": 360})\nws.insert_chart(\"E20\", column)\n",[194,1159,1160,1177,1182,1200,1226,1252,1266,1270,1274,1292,1297,1315,1341,1367,1392,1418,1433,1449,1453,1457,1462,1476,1497,1519,1540,1555,1578],{"__ignoreMap":192},[197,1161,1162,1165,1167,1169,1171,1173,1175],{"class":118,"line":199},[197,1163,1164],{"class":239},"column ",[197,1166,270],{"class":235},[197,1168,760],{"class":239},[197,1170,763],{"class":206},[197,1172,458],{"class":239},[197,1174,768],{"class":206},[197,1176,398],{"class":239},[197,1178,1179],{"class":118,"line":249},[197,1180,1181],{"class":239},"column.add_series({\n",[197,1183,1184,1186,1188,1190,1192,1194,1196,1198],{"class":118,"line":257},[197,1185,780],{"class":206},[197,1187,783],{"class":239},[197,1189,434],{"class":206},[197,1191,288],{"class":239},[197,1193,44],{"class":326},[197,1195,288],{"class":239},[197,1197,495],{"class":326},[197,1199,314],{"class":239},[197,1201,1202,1204,1206,1208,1210,1212,1214,1216,1218,1220,1222,1224],{"class":118,"line":264},[197,1203,800],{"class":206},[197,1205,323],{"class":239},[197,1207,434],{"class":206},[197,1209,288],{"class":239},[197,1211,495],{"class":326},[197,1213,288],{"class":239},[197,1215,44],{"class":326},[197,1217,288],{"class":239},[197,1219,722],{"class":326},[197,1221,288],{"class":239},[197,1223,44],{"class":326},[197,1225,314],{"class":239},[197,1227,1228,1230,1232,1234,1236,1238,1240,1242,1244,1246,1248,1250],{"class":118,"line":276},[197,1229,827],{"class":206},[197,1231,830],{"class":239},[197,1233,434],{"class":206},[197,1235,288],{"class":239},[197,1237,495],{"class":326},[197,1239,288],{"class":239},[197,1241,495],{"class":326},[197,1243,288],{"class":239},[197,1245,722],{"class":326},[197,1247,288],{"class":239},[197,1249,495],{"class":326},[197,1251,314],{"class":239},[197,1253,1254,1256,1258,1260,1262,1264],{"class":118,"line":317},[197,1255,855],{"class":206},[197,1257,858],{"class":239},[197,1259,861],{"class":206},[197,1261,458],{"class":239},[197,1263,866],{"class":206},[197,1265,869],{"class":239},[197,1267,1268],{"class":118,"line":357},[197,1269,398],{"class":239},[197,1271,1272],{"class":118,"line":395},[197,1273,261],{"emptyLinePlaceholder":260},[197,1275,1276,1279,1281,1283,1285,1287,1290],{"class":118,"line":401},[197,1277,1278],{"class":239},"line ",[197,1280,270],{"class":235},[197,1282,760],{"class":239},[197,1284,763],{"class":206},[197,1286,458],{"class":239},[197,1288,1289],{"class":206},"\"line\"",[197,1291,398],{"class":239},[197,1293,1294],{"class":118,"line":406},[197,1295,1296],{"class":239},"line.add_series({\n",[197,1298,1299,1301,1303,1305,1307,1309,1311,1313],{"class":118,"line":423},[197,1300,780],{"class":206},[197,1302,783],{"class":239},[197,1304,434],{"class":206},[197,1306,288],{"class":239},[197,1308,44],{"class":326},[197,1310,288],{"class":239},[197,1312,658],{"class":326},[197,1314,314],{"class":239},[197,1316,1317,1319,1321,1323,1325,1327,1329,1331,1333,1335,1337,1339],{"class":118,"line":439},[197,1318,800],{"class":206},[197,1320,323],{"class":239},[197,1322,434],{"class":206},[197,1324,288],{"class":239},[197,1326,495],{"class":326},[197,1328,288],{"class":239},[197,1330,44],{"class":326},[197,1332,288],{"class":239},[197,1334,722],{"class":326},[197,1336,288],{"class":239},[197,1338,44],{"class":326},[197,1340,314],{"class":239},[197,1342,1343,1345,1347,1349,1351,1353,1355,1357,1359,1361,1363,1365],{"class":118,"line":444},[197,1344,827],{"class":206},[197,1346,830],{"class":239},[197,1348,434],{"class":206},[197,1350,288],{"class":239},[197,1352,495],{"class":326},[197,1354,288],{"class":239},[197,1356,658],{"class":326},[197,1358,288],{"class":239},[197,1360,722],{"class":326},[197,1362,288],{"class":239},[197,1364,658],{"class":326},[197,1366,314],{"class":239},[197,1368,1369,1372,1374,1376,1378,1381,1383,1385,1387,1390],{"class":118,"line":477},[197,1370,1371],{"class":206},"    \"line\"",[197,1373,858],{"class":239},[197,1375,861],{"class":206},[197,1377,458],{"class":239},[197,1379,1380],{"class":206},"\"#0F766E\"",[197,1382,288],{"class":239},[197,1384,1082],{"class":206},[197,1386,458],{"class":239},[197,1388,1389],{"class":326},"2.25",[197,1391,869],{"class":239},[197,1393,1394,1397,1400,1402,1404,1407,1409,1411,1413,1416],{"class":118,"line":500},[197,1395,1396],{"class":206},"    \"marker\"",[197,1398,1399],{"class":239},":     {",[197,1401,763],{"class":206},[197,1403,458],{"class":239},[197,1405,1406],{"class":206},"\"circle\"",[197,1408,288],{"class":239},[197,1410,917],{"class":206},[197,1412,458],{"class":239},[197,1414,1415],{"class":326},"6",[197,1417,474],{"class":239},[197,1419,1420,1423,1425,1427,1429,1431],{"class":118,"line":528},[197,1421,1422],{"class":206},"                   \"fill\"",[197,1424,889],{"class":239},[197,1426,861],{"class":206},[197,1428,458],{"class":239},[197,1430,1380],{"class":206},[197,1432,934],{"class":239},[197,1434,1435,1438,1441,1443,1446],{"class":118,"line":555},[197,1436,1437],{"class":206},"    \"y2_axis\"",[197,1439,1440],{"class":239},":    ",[197,1442,461],{"class":326},[197,1444,1445],{"class":239},",                       ",[197,1447,1448],{"class":734},"# plot against the right-hand axis\n",[197,1450,1451],{"class":118,"line":560},[197,1452,398],{"class":239},[197,1454,1455],{"class":118,"line":591},[197,1456,261],{"emptyLinePlaceholder":260},[197,1458,1459],{"class":118,"line":631},[197,1460,1461],{"class":239},"column.combine(line)\n",[197,1463,1464,1467,1469,1471,1474],{"class":118,"line":642},[197,1465,1466],{"class":239},"column.set_title({",[197,1468,946],{"class":206},[197,1470,458],{"class":239},[197,1472,1473],{"class":206},"\"Amount and margin by month\"",[197,1475,398],{"class":239},[197,1477,1478,1481,1483,1485,1487,1489,1491,1493,1495],{"class":118,"line":653},[197,1479,1480],{"class":239},"column.set_y_axis({",[197,1482,946],{"class":206},[197,1484,458],{"class":239},[197,1486,580],{"class":206},[197,1488,288],{"class":239},[197,1490,510],{"class":206},[197,1492,458],{"class":239},[197,1494,1025],{"class":206},[197,1496,398],{"class":239},[197,1498,1499,1502,1504,1506,1508,1510,1512,1514,1517],{"class":118,"line":664},[197,1500,1501],{"class":239},"column.set_y2_axis({",[197,1503,946],{"class":206},[197,1505,458],{"class":239},[197,1507,585],{"class":206},[197,1509,288],{"class":239},[197,1511,510],{"class":206},[197,1513,458],{"class":239},[197,1515,1516],{"class":206},"\"0%\"",[197,1518,474],{"class":239},[197,1520,1521,1524,1526,1528,1530,1533,1535,1538],{"class":118,"line":669},[197,1522,1523],{"class":206},"                    \"min\"",[197,1525,458],{"class":239},[197,1527,44],{"class":326},[197,1529,288],{"class":239},[197,1531,1532],{"class":206},"\"max\"",[197,1534,458],{"class":239},[197,1536,1537],{"class":326},"0.5",[197,1539,398],{"class":239},[197,1541,1542,1545,1548,1550,1553],{"class":118,"line":685},[197,1543,1544],{"class":239},"column.set_legend({",[197,1546,1547],{"class":206},"\"position\"",[197,1549,458],{"class":239},[197,1551,1552],{"class":206},"\"bottom\"",[197,1554,398],{"class":239},[197,1556,1557,1560,1562,1564,1567,1569,1571,1573,1576],{"class":118,"line":700},[197,1558,1559],{"class":239},"column.set_size({",[197,1561,1082],{"class":206},[197,1563,458],{"class":239},[197,1565,1566],{"class":326},"720",[197,1568,288],{"class":239},[197,1570,1092],{"class":206},[197,1572,458],{"class":239},[197,1574,1575],{"class":326},"360",[197,1577,398],{"class":239},[197,1579,1580,1582,1585],{"class":118,"line":714},[197,1581,1104],{"class":239},[197,1583,1584],{"class":206},"\"E20\"",[197,1586,1587],{"class":239},", column)\n",[10,1589,1590,1593,1594,1597,1598,1601],{},[194,1591,1592],{},"combine()"," is called on the primary chart and takes the secondary one; only the primary chart is inserted. Fixing ",[194,1595,1596],{},"min"," and ",[194,1599,1600],{},"max"," on the secondary axis is worth doing deliberately — an auto-scaled percentage axis rescales every month as the data moves, which makes two consecutive reports look different when nothing changed. Here the legend earns its place, because there are now two series to tell apart.",[23,1603,32,1607,32,1610,32,1613,32,1615,32,1620,32,1626,32,1629,32,1631,32,1636,32,1640,32,1643,32,1648,32,1651,32,1654,32,1658,32,1663,32,1666,32,1671,32,1676,32,1681,32,1687,32,1693,32,1697,32,1701,32,1704,32,1707,32,1711,32,1715,32,1718,32,1721,32,1724,32,1727,32,1730,32,1734,32,1740,32,1745,32,1748],{"viewBox":25,"role":26,"ariaLabelledBy":1604,"xmlns":30,"style":31},[1605,1606],"xc-combo-t","xc-combo-d",[34,1608,1609],{"id":1605},"A combined chart with a fixed secondary axis",[38,1611,1612],{"id":1606},"Columns are plotted against the left axis in currency and a line against a right-hand axis in percent. The secondary axis is pinned from zero to fifty percent, so the line's position means the same thing in this month's report as it did in last month's.",[42,1614],{"x":44,"y":44,"width":45,"height":46,"fill":47},[49,1616,1619],{"x":1617,"y":57,"style":1618},"370","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Amount and margin by month",[118,1621],{"x1":1622,"y1":1623,"x2":1622,"y2":1624,"stroke":1625,"style":155},"70","52","192","var(--line,#cdd5e6)",[118,1627],{"x1":1622,"y1":1624,"x2":1628,"y2":1624,"stroke":1625,"style":155},"660",[118,1630],{"x1":1628,"y1":1623,"x2":1628,"y2":1624,"stroke":1625,"style":155},[49,1632,1635],{"x":152,"y":1633,"style":1634},"60","font-size:10.5px;fill:var(--muted,#5b6780);text-anchor:middle","700",[49,1637,1639],{"x":152,"y":1638,"style":1634},"128","350",[49,1641,44],{"x":152,"y":1642,"style":1634},"196",[49,1644,1647],{"x":1645,"y":1633,"style":1646},"694","font-size:10.5px;fill:var(--teal-ink,#0b6157);text-anchor:middle","50%",[49,1649,1650],{"x":1645,"y":1638,"style":1646},"25%",[49,1652,1653],{"x":1645,"y":1642,"style":1646},"0%",[42,1655],{"x":1656,"y":71,"width":1657,"height":123,"fill":139},"92","56",[42,1659],{"x":1660,"y":1661,"width":1657,"height":1662,"fill":139},"188","115","77",[42,1664],{"x":1665,"y":1656,"width":1657,"height":59,"fill":139},"284",[42,1667],{"x":1668,"y":1669,"width":1657,"height":1670,"fill":139},"380","99","93",[42,1672],{"x":1673,"y":1674,"width":1657,"height":1675,"fill":139},"476","74","118",[42,1677],{"x":1678,"y":1679,"width":1657,"height":1680,"fill":139},"572","67","125",[1682,1683],"polyline",{"points":1684,"fill":1685,"stroke":89,"style":1686},"120,105 216,111 312,97 408,100 504,90 600,84","none","stroke-width:2.5px",[1688,1689],"circle",{"cx":1690,"cy":1691,"r":1692,"fill":147},"120","105","4",[1688,1694],{"cx":1695,"cy":1696,"r":1692,"fill":147},"216","111",[1688,1698],{"cx":1699,"cy":1700,"r":1692,"fill":147},"312","97",[1688,1702],{"cx":1703,"cy":59,"r":1692,"fill":147},"408",[1688,1705],{"cx":1706,"cy":83,"r":1692,"fill":147},"504",[1688,1708],{"cx":1709,"cy":1710,"r":1692,"fill":147},"600","84",[49,1712,1714],{"x":1690,"y":1713,"style":1634},"208","Jan",[49,1716,1717],{"x":1695,"y":1713,"style":1634},"Feb",[49,1719,1720],{"x":1699,"y":1713,"style":1634},"Mar",[49,1722,1723],{"x":1703,"y":1713,"style":1634},"Apr",[49,1725,1726],{"x":1706,"y":1713,"style":1634},"May",[49,1728,1729],{"x":1709,"y":1713,"style":1634},"Jun",[42,1731],{"x":1732,"y":1733,"width":695,"height":1003,"fill":139},"252","222",[49,1735,1739],{"x":1736,"y":1737,"style":1738},"276","231","font-size:11px;fill:var(--text,#172033)","Amount (left)",[118,1741],{"x1":1742,"y1":1743,"x2":1744,"y2":1743,"stroke":89,"style":1686},"392","227","416",[1688,1746],{"cx":1747,"cy":1743,"r":1692,"fill":147},"404",[49,1749,1751],{"x":1750,"y":1737,"style":1738},"426","Margin (right, fixed 0–50%)",[182,1753,1755],{"id":1754},"step-3b-place-it-where-it-will-not-be-in-the-way","Step 3b: Place it where it will not be in the way",[10,1757,1758,1759,1761],{},"Anchoring looks trivial until a reader widens a column and the chart lands on top of the table. ",[194,1760,1142],{}," takes the same positioning options as an image, and the third one is the setting worth choosing deliberately:",[23,1763,32,1768,32,1771,32,1774,32,1776,32,1780,32,1785,32,1789,32,1792,32,1795,32,1798,32,1801,32,1805,32,1808,32,1811,32,1814,32,1817,32,1820,32,1825,32,1828,32,1831,32,1834],{"viewBox":1764,"role":26,"ariaLabelledBy":1765,"xmlns":30,"style":31},"0 0 740 216",[1766,1767],"xc-pos-t","xc-pos-d",[34,1769,1770],{"id":1766},"Three anchoring behaviours when rows and columns are resized",[38,1772,1773],{"id":1767},"Object position one moves and sizes the chart with the cells beneath it, so widening a column stretches it. Position two moves it but keeps its size, which is usually what a reader expects. Position three pins it in place, so the chart stays put while the table grows underneath it.",[42,1775],{"x":44,"y":44,"width":45,"height":1695,"fill":47},[42,1777],{"x":1778,"y":1779,"width":178,"height":51,"rx":695,"fill":79,"stroke":80,"style":155},"16","34",[49,1781,1784],{"x":70,"y":1782,"style":1783},"62","font-size:12px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","position 1",[49,1786,1788],{"x":70,"y":83,"style":1787},"font-size:11.5px;fill:var(--text,#172033);text-anchor:middle","moves and sizes",[49,1790,1791],{"x":70,"y":164,"style":1787},"with the cells",[49,1793,1794],{"x":70,"y":110,"style":179},"a widened column",[49,1796,1797],{"x":70,"y":171,"style":179},"stretches the chart",[42,1799],{"x":1800,"y":1779,"width":178,"height":51,"rx":695,"fill":88,"stroke":89,"style":155},"256",[49,1802,1804],{"x":1617,"y":1782,"style":1803},"font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","position 2",[49,1806,1807],{"x":1617,"y":83,"style":1787},"moves, keeps its size",[49,1809,1810],{"x":1617,"y":164,"style":1787},"the usual choice",[49,1812,1813],{"x":1617,"y":110,"style":179},"stays beside its table",[49,1815,1816],{"x":1617,"y":171,"style":179},"without distorting",[42,1818],{"x":1819,"y":1779,"width":178,"height":51,"rx":695,"fill":154,"stroke":124,"style":155},"496",[49,1821,1824],{"x":1822,"y":1782,"style":1823},"610","font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","position 3",[49,1826,1827],{"x":1822,"y":83,"style":1787},"pinned in place",[49,1829,1830],{"x":1822,"y":164,"style":1787},"ignores the cells",[49,1832,1833],{"x":1822,"y":110,"style":179},"right for a dashboard",[49,1835,1836],{"x":1822,"y":171,"style":179},"laid out by hand",[187,1838,1840],{"className":226,"code":1839,"language":228,"meta":192,"style":192},"ws.insert_chart(\"E2\", chart, {\"x_offset\": 8, \"y_offset\": 4,\n                              \"object_position\": 2})\n",[194,1841,1842,1869],{"__ignoreMap":192},[197,1843,1844,1846,1848,1851,1854,1856,1858,1860,1863,1865,1867],{"class":118,"line":199},[197,1845,1104],{"class":239},[197,1847,1107],{"class":206},[197,1849,1850],{"class":239},", chart, {",[197,1852,1853],{"class":206},"\"x_offset\"",[197,1855,458],{"class":239},[197,1857,153],{"class":326},[197,1859,288],{"class":239},[197,1861,1862],{"class":206},"\"y_offset\"",[197,1864,458],{"class":239},[197,1866,1692],{"class":326},[197,1868,474],{"class":239},[197,1870,1871,1874,1876,1878],{"class":118,"line":249},[197,1872,1873],{"class":206},"                              \"object_position\"",[197,1875,458],{"class":239},[197,1877,658],{"class":326},[197,1879,398],{"class":239},[10,1881,1882,1883,1886],{},"The offsets nudge the chart a few pixels off the cell's corner so it does not sit flush against the gridline, which reads as deliberate placement rather than a dropped object. Anchor at a column beyond the last one the data uses — ",[194,1884,1885],{},"E2"," for a three-column table — so no plausible column resize can put the chart over the numbers.",[182,1888,1890],{"id":1889},"step-4-give-a-headline-chart-its-own-tab","Step 4: Give a headline chart its own tab",[10,1892,1893],{},"For a chart that is the point of the report rather than an accompaniment, a chartsheet is a full-page tab with no cells:",[187,1895,1897],{"className":226,"code":1896,"language":228,"meta":192,"style":192},"cs = wb.add_chartsheet(\"Trend\")\ncs.set_chart(column)          # one chart, full page\ncs.activate()                 # the tab the workbook opens on\nwb.close()\n",[194,1898,1899,1914,1922,1930],{"__ignoreMap":192},[197,1900,1901,1904,1906,1909,1912],{"class":118,"line":199},[197,1902,1903],{"class":239},"cs ",[197,1905,270],{"class":235},[197,1907,1908],{"class":239}," wb.add_chartsheet(",[197,1910,1911],{"class":206},"\"Trend\"",[197,1913,420],{"class":239},[197,1915,1916,1919],{"class":118,"line":249},[197,1917,1918],{"class":239},"cs.set_chart(column)          ",[197,1920,1921],{"class":734},"# one chart, full page\n",[197,1923,1924,1927],{"class":118,"line":257},[197,1925,1926],{"class":239},"cs.activate()                 ",[197,1928,1929],{"class":734},"# the tab the workbook opens on\n",[197,1931,1932],{"class":118,"line":264},[197,1933,1934],{"class":239},"wb.close()\n",[10,1936,1937,1938,1941,1942,1946],{},"A chartsheet holds exactly one chart and cannot contain data, which is precisely why it works for a headline: nobody can accidentally type into it. ",[194,1939,1940],{},"activate()"," decides which tab is selected when the file opens — worth setting on any ",[17,1943,1945],{"href":1944},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002F","multi-sheet report",", because the default is whichever sheet was added first.",[182,1948,1950],{"id":1949},"common-pitfalls-and-gotchas","Common pitfalls and gotchas",[1952,1953,1954,1970],"table",{},[1955,1956,1957],"thead",{},[1958,1959,1960,1964,1967],"tr",{},[1961,1962,1963],"th",{},"Symptom",[1961,1965,1966],{},"Cause",[1961,1968,1969],{},"Fix",[1971,1972,1973,1988,2003,2021,2035,2051,2063,2074],"tbody",{},[1958,1974,1975,1979,1982],{},[1976,1977,1978],"td",{},"Chart has empty space on the right",[1976,1980,1981],{},"Range extends past the written rows",[1976,1983,1984,1985],{},"Build ranges from ",[194,1986,1987],{},"len(df)",[1958,1989,1990,1993,1996],{},[1976,1991,1992],{},"Chart is empty",[1976,1994,1995],{},"Sheet name in the range does not match",[1976,1997,1998,1999,2002],{},"Use the exact ",[194,2000,2001],{},"add_worksheet"," name",[1958,2004,2005,2008,2015],{},[1976,2006,2007],{},"Series name shows as \"Series 1\"",[1976,2009,2010,2011,2014],{},"No ",[194,2012,2013],{},"name"," given",[1976,2016,2017,2018,2020],{},"Point ",[194,2019,2013],{}," at the header cell",[1958,2022,2023,2026,2029],{},[1976,2024,2025],{},"Percentages plot as a flat line",[1976,2027,2028],{},"Sharing the currency axis",[1976,2030,2031,2032],{},"Put them on ",[194,2033,2034],{},"y2_axis",[1958,2036,2037,2040,2043],{},[1976,2038,2039],{},"Axis rescales every month",[1976,2041,2042],{},"Auto min and max",[1976,2044,2045,2046,1597,2048,2050],{},"Fix ",[194,2047,1596],{},[194,2049,1600],{}," explicitly",[1958,2052,2053,2056,2059],{},[1976,2054,2055],{},"Legend covers a fifth of the chart",[1976,2057,2058],{},"Default legend on a single series",[1976,2060,2061],{},[194,2062,1128],{},[1958,2064,2065,2068,2071],{},[1976,2066,2067],{},"Chart sits on top of the data",[1976,2069,2070],{},"Anchored at a cell inside the table",[1976,2072,2073],{},"Insert well to the right of the last column",[1958,2075,2076,2079,2082],{},[1976,2077,2078],{},"Data labels unreadable",[1976,2080,2081],{},"Default size on a dense chart",[1976,2083,2084,2085,2088,2089],{},"Set ",[194,2086,2087],{},"font"," size and colour in ",[194,2090,1132],{},[182,2092,2094],{"id":2093},"performance-and-scale-notes","Performance and scale notes",[10,2096,2097,2098,2102],{},"Charts are cheap to write — the definition is a few kilobytes regardless of how many points it references — but they are not cheap to ",[2099,2100,2101],"em",{},"render",". A scatter or line chart over 50,000 points makes Excel slow to open and slower to scroll, and the picture is unreadable anyway. Aggregate before charting: plot the monthly total, not every transaction, and keep the detail on its own sheet for anyone who wants to filter it.",[10,2104,2105,2106,2110],{},"Where a chart genuinely needs tens of thousands of points, consider rendering it as an image with matplotlib and inserting that instead. The result is not interactive, but it opens instantly; ",[17,2107,2109],{"href":2108},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002F","Insert an Image into Excel"," covers the placement and anchoring.",[182,2112,2114],{"id":2113},"conclusion","Conclusion",[10,2116,2117],{},"A chart in xlsxwriter is three ranges and a handful of styling decisions. Compute the ranges from the row count so the chart follows the data, format the axes so the numbers read the way the table does, drop the legend when there is one series and keep it when there are two, and fix the secondary axis so consecutive reports are comparable. When the chart is the report, put it on a chartsheet and make that the tab the workbook opens on.",[182,2119,2121],{"id":2120},"frequently-asked-questions","Frequently asked questions",[10,2123,2124,2128,2129,2131],{},[2125,2126,2127],"strong",{},"Why is part of my chart blank?","\nThe series range extends past the rows that were actually written. Build the range from ",[194,2130,1987],{}," rather than typing an end row, and Excel will plot exactly what exists.",[10,2133,2134,2137,2138,2140,2141,2143],{},[2125,2135,2136],{},"Can I combine a column chart and a line chart?","\nYes. Create both chart objects, then call ",[194,2139,1592],{}," on the primary one. Put the line on a secondary axis with ",[194,2142,2034],{}," when the two series use different units.",[10,2145,2146,2149],{},[2125,2147,2148],{},"Is this a real Excel chart or an image?","\nA real chart object. It recalculates when a reader edits the data, and it can be restyled in Excel like any hand-made chart — unlike a matplotlib image, which is a picture.",[10,2151,2152,2155,2156,1121,2159,2161],{},[2125,2153,2154],{},"How do I put the chart on its own tab?","\nUse ",[194,2157,2158],{},"add_chartsheet",[194,2160,1142],{},". A chartsheet holds one full-page chart and no cells, which suits a headline visual in a multi-sheet report.",[182,2163,2165],{"id":2164},"related","Related",[10,2167,2168],{},"Up to the parent guide:",[2170,2171,2172],"ul",{},[2173,2174,2175,2177],"li",{},[17,2176,20],{"href":19}," — the workbook model these charts are inserted into.",[10,2179,2180],{},"Related guides:",[2170,2182,2183,2190,2197,2204],{},[2173,2184,2185,2189],{},[17,2186,2188],{"href":2187},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002Fcreate-bar-chart-in-excel-with-openpyxl\u002F","Create a Bar Chart in Excel with openpyxl"," — the same chart on the other engine.",[2173,2191,2192,2196],{},[17,2193,2195],{"href":2194},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002Fadd-line-chart-to-excel-report-with-python\u002F","Add a Line Chart to an Excel Report with Python"," — time series and axis handling.",[2173,2198,2199,2203],{},[17,2200,2202],{"href":2201},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-a-formatted-excel-report-with-xlsxwriter\u002F","Write a Formatted Excel Report with xlsxwriter"," — the styled table this chart sits beside.",[2173,2205,2206,2210],{},[17,2207,2209],{"href":2208},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fadd-summary-sheet-to-excel-report-python\u002F","Add a Summary Sheet to an Excel Report in Python"," — where a headline chart usually belongs.",[2212,2213,2214],"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 .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}",{"title":192,"searchDepth":249,"depth":249,"links":2216},[2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227],{"id":184,"depth":249,"text":185},{"id":219,"depth":249,"text":220},{"id":744,"depth":249,"text":745},{"id":1150,"depth":249,"text":1151},{"id":1754,"depth":249,"text":1755},{"id":1889,"depth":249,"text":1890},{"id":1949,"depth":249,"text":1950},{"id":2093,"depth":249,"text":2094},{"id":2113,"depth":249,"text":2114},{"id":2120,"depth":249,"text":2121},{"id":2164,"depth":249,"text":2165},"2026-08-10","Insert a real Excel chart from Python: series built from row counts, axis and label formatting, a combined column-and-line chart on a secondary axis, and placement that survives changing data.","md",[2232,2234,2236,2238],{"q":2127,"a":2233},"The series range extends past the rows that were actually written. Build the range from len(df) rather than typing an end row, and Excel will plot exactly what exists.",{"q":2136,"a":2235},"Yes. Create both chart objects, then call combine() on the primary one. Put the line on a secondary axis with y2_axis when the two series use different units.",{"q":2148,"a":2237},"A real chart object. It recalculates when a reader edits the data, and it can be restyled in Excel like any hand-made chart — unlike a matplotlib image, which is a picture.",{"q":2154,"a":2239},"Use add_chartsheet instead of insert_chart. A chartsheet holds one full-page chart and no cells, which suits a headline visual in a multi-sheet report.",{"breadcrumb":2241},[2242,2245,2248,2249],{"name":2243,"item":2244},"Home","\u002F",{"name":2246,"item":2247},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":20,"item":19},{"name":5,"item":2250},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-a-chart-to-an-excel-file-with-xlsxwriter\u002F","\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-a-chart-to-an-excel-file-with-xlsxwriter",{"title":2253,"description":2254},"Add a Chart to Excel with xlsxwriter (Python)","Create native Excel charts with xlsxwriter — column, line and pie types, computed series ranges, axis number formats, data labels, combined charts with a secondary axis and chartsheets.","add-a-chart-to-an-excel-file-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-a-chart-to-an-excel-file-with-xlsxwriter\u002Findex","how-to","e97_1orf1AwJS7wyYccHhryxf19Vp4s9Hb7FmhCve_A",[2260,2263],{"title":20,"path":2261,"stem":2262,"children":-1},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Findex",{"title":2264,"path":2265,"stem":2266,"children":-1},"Apply Conditional Formatting with xlsxwriter","\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fapply-conditional-formatting-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fapply-conditional-formatting-with-xlsxwriter\u002Findex",1786800027340]