[{"data":1,"prerenderedAt":2540},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fcombine-chart-types-and-chartsheets-with-xlsxwriter":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fcombine-chart-types-and-chartsheets-with-xlsxwriter":2507,"ancestors:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fcombine-chart-types-and-chartsheets-with-xlsxwriter":2516,"children:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fcombine-chart-types-and-chartsheets-with-xlsxwriter":2521,"related:\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fcombine-chart-types-and-chartsheets-with-xlsxwriter":2522},{"id":4,"title":5,"body":6,"dateModified":2475,"datePublished":2475,"description":2476,"extension":2477,"faq":2478,"keyword":2487,"kind":2488,"meta":2489,"navigation":117,"path":2497,"seo":2498,"slug":2500,"stem":2501,"topics":2502,"type":2505,"__hash__":2506},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fcombine-chart-types-and-chartsheets-with-xlsxwriter\u002Findex.md","Combine Chart Types and Chartsheets with XlsxWriter",{"type":7,"value":8,"toc":2464},"minimark",[9,28,33,61,64,68,674,681,685,696,1093,1120,1285,1289,1296,1676,1686,1782,1935,1939,1942,1996,2011,2316,2323,2327,2376,2380,2399,2403,2409,2415,2421,2427,2431,2460],[10,11,12,13,17,18,21,22,27],"p",{},"Two numbers that belong together often have different scales: revenue in hundreds of thousands and margin as a percentage, or orders in units and average order value in currency. Plotting both on one axis flattens one of them into a line along the bottom. A combination chart — columns for one series and a line for the other, the line on its own axis on the right — shows both at once, and it is one of the most requested charts in management packs. Another frequent request is a chart that fills a whole tab, sized to the window and ready to print, rather than floating over cells. XlsxWriter supports both: ",[14,15,16],"code",{},"chart.combine()"," merges two chart types, and ",[14,19,20],{},"add_chartsheet()"," creates a sheet that holds a single chart. This page builds a column-and-line chart with a secondary axis, a stacked column chart with a total line, places them on chartsheets, and checks the generated chart definitions. It belongs to ",[23,24,26],"a",{"href":25},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002F","Building Excel Reports with xlsxwriter",".",[29,30,32],"h2",{"id":31},"prerequisites","Prerequisites",[34,35,40],"pre",{"className":36,"code":37,"language":38,"meta":39,"style":39},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install xlsxwriter pandas\n","bash","",[14,41,42],{"__ignoreMap":39},[43,44,47,51,55,58],"span",{"class":45,"line":46},"line",1,[43,48,50],{"class":49},"sMTad","pip",[43,52,54],{"class":53},"srMev"," install",[43,56,57],{"class":53}," xlsxwriter",[43,59,60],{"class":53}," pandas\n",[10,62,63],{},"The data is twelve months of revenue and gross margin per product line, summarised with pandas. Charts in Excel always read their data from cells, so the summary is written to a data sheet first and every chart refers to it.",[29,65,67],{"id":66},"step-1-summarise-and-write-the-chart-data","Step 1 — Summarise and write the chart data",[34,69,73],{"className":70,"code":71,"language":72,"meta":39,"style":39},"language-python shiki shiki-themes github-light github-dark-high-contrast","import numpy as np\nimport pandas as pd\nimport xlsxwriter\n\nrng = np.random.default_rng(8)\nmonths = pd.period_range(\"2025-10\", \"2026-09\", freq=\"M\").strftime(\"%b %y\")\nlines = [\"Hardware\", \"Services\", \"Software\"]\nrevenue = pd.DataFrame({ln: (base * (1 + 0.02 * np.arange(12)) * rng.uniform(0.9, 1.1, 12)).round(-2)\n                        for ln, base in zip(lines, [180_000, 95_000, 60_000])}, index=months)\nmargin = pd.Series((0.31 + 0.03 * np.sin(np.arange(12) \u002F 2) + rng.normal(0, 0.008, 12)).round(3), index=months, name=\"Margin\")\nsummary = revenue.assign(Total=revenue.sum(axis=1), Margin=margin)\n\nwb = xlsxwriter.Workbook(\"charts.xlsx\")\ndata = wb.add_worksheet(\"Data\")\nbold = wb.add_format({\"bold\": True})\ndata.write_row(0, 0, [\"Month\", *summary.columns], bold)\nfor r, (month, row) in enumerate(summary.iterrows(), start=1):\n    data.write(r, 0, month)\n    data.write_row(r, 1, row.tolist())\ndata.set_column(0, 0, 9)\ndata.set_column(1, 4, 11, wb.add_format({\"num_format\": \"#,##0\"}))\ndata.set_column(5, 5, 9, wb.add_format({\"num_format\": \"0.0%\"}))\nn = len(summary)\nprint(summary.head(3).to_string())\n","python",[14,74,75,91,104,112,119,138,184,211,277,319,399,435,440,456,472,495,520,547,558,569,588,619,646,660],{"__ignoreMap":39},[43,76,77,81,85,88],{"class":45,"line":46},[43,78,80],{"class":79},"s-kum","import",[43,82,84],{"class":83},"skGVy"," numpy ",[43,86,87],{"class":79},"as",[43,89,90],{"class":83}," np\n",[43,92,94,96,99,101],{"class":45,"line":93},2,[43,95,80],{"class":79},[43,97,98],{"class":83}," pandas ",[43,100,87],{"class":79},[43,102,103],{"class":83}," pd\n",[43,105,107,109],{"class":45,"line":106},3,[43,108,80],{"class":79},[43,110,111],{"class":83}," xlsxwriter\n",[43,113,115],{"class":45,"line":114},4,[43,116,118],{"emptyLinePlaceholder":117},true,"\n",[43,120,122,125,128,131,135],{"class":45,"line":121},5,[43,123,124],{"class":83},"rng ",[43,126,127],{"class":79},"=",[43,129,130],{"class":83}," np.random.default_rng(",[43,132,134],{"class":133},"sP0c6","8",[43,136,137],{"class":83},")\n",[43,139,141,144,146,149,152,155,158,160,164,166,169,172,175,179,182],{"class":45,"line":140},6,[43,142,143],{"class":83},"months ",[43,145,127],{"class":79},[43,147,148],{"class":83}," pd.period_range(",[43,150,151],{"class":53},"\"2025-10\"",[43,153,154],{"class":83},", ",[43,156,157],{"class":53},"\"2026-09\"",[43,159,154],{"class":83},[43,161,163],{"class":162},"sa561","freq",[43,165,127],{"class":79},[43,167,168],{"class":53},"\"M\"",[43,170,171],{"class":83},").strftime(",[43,173,174],{"class":53},"\"",[43,176,178],{"class":177},"sSjpA","%b",[43,180,181],{"class":53}," %y\"",[43,183,137],{"class":83},[43,185,187,190,192,195,198,200,203,205,208],{"class":45,"line":186},7,[43,188,189],{"class":83},"lines ",[43,191,127],{"class":79},[43,193,194],{"class":83}," [",[43,196,197],{"class":53},"\"Hardware\"",[43,199,154],{"class":83},[43,201,202],{"class":53},"\"Services\"",[43,204,154],{"class":83},[43,206,207],{"class":53},"\"Software\"",[43,209,210],{"class":83},"]\n",[43,212,214,217,219,222,225,228,231,234,237,240,243,246,249,251,254,257,259,262,264,266,269,272,275],{"class":45,"line":213},8,[43,215,216],{"class":83},"revenue ",[43,218,127],{"class":79},[43,220,221],{"class":83}," pd.DataFrame({ln: (base ",[43,223,224],{"class":79},"*",[43,226,227],{"class":83}," (",[43,229,230],{"class":133},"1",[43,232,233],{"class":79}," +",[43,235,236],{"class":133}," 0.02",[43,238,239],{"class":79}," *",[43,241,242],{"class":83}," np.arange(",[43,244,245],{"class":133},"12",[43,247,248],{"class":83},")) ",[43,250,224],{"class":79},[43,252,253],{"class":83}," rng.uniform(",[43,255,256],{"class":133},"0.9",[43,258,154],{"class":83},[43,260,261],{"class":133},"1.1",[43,263,154],{"class":83},[43,265,245],{"class":133},[43,267,268],{"class":83},")).round(",[43,270,271],{"class":79},"-",[43,273,274],{"class":133},"2",[43,276,137],{"class":83},[43,278,280,283,286,289,292,295,298,300,303,305,308,311,314,316],{"class":45,"line":279},9,[43,281,282],{"class":79},"                        for",[43,284,285],{"class":83}," ln, base ",[43,287,288],{"class":79},"in",[43,290,291],{"class":133}," zip",[43,293,294],{"class":83},"(lines, [",[43,296,297],{"class":133},"180_000",[43,299,154],{"class":83},[43,301,302],{"class":133},"95_000",[43,304,154],{"class":83},[43,306,307],{"class":133},"60_000",[43,309,310],{"class":83},"])}, ",[43,312,313],{"class":162},"index",[43,315,127],{"class":79},[43,317,318],{"class":83},"months)\n",[43,320,322,325,327,330,333,335,338,340,343,345,348,351,354,356,359,362,365,367,370,372,374,376,379,382,384,386,389,392,394,397],{"class":45,"line":321},10,[43,323,324],{"class":83},"margin ",[43,326,127],{"class":79},[43,328,329],{"class":83}," pd.Series((",[43,331,332],{"class":133},"0.31",[43,334,233],{"class":79},[43,336,337],{"class":133}," 0.03",[43,339,239],{"class":79},[43,341,342],{"class":83}," np.sin(np.arange(",[43,344,245],{"class":133},[43,346,347],{"class":83},") ",[43,349,350],{"class":79},"\u002F",[43,352,353],{"class":133}," 2",[43,355,347],{"class":83},[43,357,358],{"class":79},"+",[43,360,361],{"class":83}," rng.normal(",[43,363,364],{"class":133},"0",[43,366,154],{"class":83},[43,368,369],{"class":133},"0.008",[43,371,154],{"class":83},[43,373,245],{"class":133},[43,375,268],{"class":83},[43,377,378],{"class":133},"3",[43,380,381],{"class":83},"), ",[43,383,313],{"class":162},[43,385,127],{"class":79},[43,387,388],{"class":83},"months, ",[43,390,391],{"class":162},"name",[43,393,127],{"class":79},[43,395,396],{"class":53},"\"Margin\"",[43,398,137],{"class":83},[43,400,402,405,407,410,413,415,418,421,423,425,427,430,432],{"class":45,"line":401},11,[43,403,404],{"class":83},"summary ",[43,406,127],{"class":79},[43,408,409],{"class":83}," revenue.assign(",[43,411,412],{"class":162},"Total",[43,414,127],{"class":79},[43,416,417],{"class":83},"revenue.sum(",[43,419,420],{"class":162},"axis",[43,422,127],{"class":79},[43,424,230],{"class":133},[43,426,381],{"class":83},[43,428,429],{"class":162},"Margin",[43,431,127],{"class":79},[43,433,434],{"class":83},"margin)\n",[43,436,438],{"class":45,"line":437},12,[43,439,118],{"emptyLinePlaceholder":117},[43,441,443,446,448,451,454],{"class":45,"line":442},13,[43,444,445],{"class":83},"wb ",[43,447,127],{"class":79},[43,449,450],{"class":83}," xlsxwriter.Workbook(",[43,452,453],{"class":53},"\"charts.xlsx\"",[43,455,137],{"class":83},[43,457,459,462,464,467,470],{"class":45,"line":458},14,[43,460,461],{"class":83},"data ",[43,463,127],{"class":79},[43,465,466],{"class":83}," wb.add_worksheet(",[43,468,469],{"class":53},"\"Data\"",[43,471,137],{"class":83},[43,473,475,478,480,483,486,489,492],{"class":45,"line":474},15,[43,476,477],{"class":83},"bold ",[43,479,127],{"class":79},[43,481,482],{"class":83}," wb.add_format({",[43,484,485],{"class":53},"\"bold\"",[43,487,488],{"class":83},": ",[43,490,491],{"class":133},"True",[43,493,494],{"class":83},"})\n",[43,496,498,501,503,505,507,510,513,515,517],{"class":45,"line":497},16,[43,499,500],{"class":83},"data.write_row(",[43,502,364],{"class":133},[43,504,154],{"class":83},[43,506,364],{"class":133},[43,508,509],{"class":83},", [",[43,511,512],{"class":53},"\"Month\"",[43,514,154],{"class":83},[43,516,224],{"class":79},[43,518,519],{"class":83},"summary.columns], bold)\n",[43,521,523,526,529,531,534,537,540,542,544],{"class":45,"line":522},17,[43,524,525],{"class":79},"for",[43,527,528],{"class":83}," r, (month, row) ",[43,530,288],{"class":79},[43,532,533],{"class":133}," enumerate",[43,535,536],{"class":83},"(summary.iterrows(), ",[43,538,539],{"class":162},"start",[43,541,127],{"class":79},[43,543,230],{"class":133},[43,545,546],{"class":83},"):\n",[43,548,550,553,555],{"class":45,"line":549},18,[43,551,552],{"class":83},"    data.write(r, ",[43,554,364],{"class":133},[43,556,557],{"class":83},", month)\n",[43,559,561,564,566],{"class":45,"line":560},19,[43,562,563],{"class":83},"    data.write_row(r, ",[43,565,230],{"class":133},[43,567,568],{"class":83},", row.tolist())\n",[43,570,572,575,577,579,581,583,586],{"class":45,"line":571},20,[43,573,574],{"class":83},"data.set_column(",[43,576,364],{"class":133},[43,578,154],{"class":83},[43,580,364],{"class":133},[43,582,154],{"class":83},[43,584,585],{"class":133},"9",[43,587,137],{"class":83},[43,589,591,593,595,597,600,602,605,608,611,613,616],{"class":45,"line":590},21,[43,592,574],{"class":83},[43,594,230],{"class":133},[43,596,154],{"class":83},[43,598,599],{"class":133},"4",[43,601,154],{"class":83},[43,603,604],{"class":133},"11",[43,606,607],{"class":83},", wb.add_format({",[43,609,610],{"class":53},"\"num_format\"",[43,612,488],{"class":83},[43,614,615],{"class":53},"\"#,##0\"",[43,617,618],{"class":83},"}))\n",[43,620,622,624,627,629,631,633,635,637,639,641,644],{"class":45,"line":621},22,[43,623,574],{"class":83},[43,625,626],{"class":133},"5",[43,628,154],{"class":83},[43,630,626],{"class":133},[43,632,154],{"class":83},[43,634,585],{"class":133},[43,636,607],{"class":83},[43,638,610],{"class":53},[43,640,488],{"class":83},[43,642,643],{"class":53},"\"0.0%\"",[43,645,618],{"class":83},[43,647,649,652,654,657],{"class":45,"line":648},23,[43,650,651],{"class":83},"n ",[43,653,127],{"class":79},[43,655,656],{"class":133}," len",[43,658,659],{"class":83},"(summary)\n",[43,661,663,666,669,671],{"class":45,"line":662},24,[43,664,665],{"class":133},"print",[43,667,668],{"class":83},"(summary.head(",[43,670,378],{"class":133},[43,672,673],{"class":83},").to_string())\n",[10,675,676,677,680],{},"The months are written as text labels (",[14,678,679],{},"Oct 25",") rather than dates, so the chart uses them as categories exactly as written. Columns B to D hold revenue by product line, E the total and F the margin percentage. Every chart below refers to these cells by sheet name, row and column, so if the data changes the charts follow.",[29,682,684],{"id":683},"step-2-columns-and-a-line-on-a-secondary-axis","Step 2 — Columns and a line on a secondary axis",[10,686,687,688,691,692,695],{},"Create a column chart and a line chart separately, put the line on the secondary axis with ",[14,689,690],{},"y2_axis",", and merge them with ",[14,693,694],{},"combine()",":",[34,697,699],{"className":70,"code":698,"language":72,"meta":39,"style":39},"col = wb.add_chart({\"type\": \"column\"})\ncol.add_series({\"name\": [\"Data\", 0, 4], \"categories\": [\"Data\", 1, 0, n, 0], \"values\": [\"Data\", 1, 4, n, 4],\n                \"fill\": {\"color\": \"#1F6FEB\"}, \"gap\": 60})\nline = wb.add_chart({\"type\": \"line\"})\nline.add_series({\"name\": [\"Data\", 0, 5], \"categories\": [\"Data\", 1, 0, n, 0], \"values\": [\"Data\", 1, 5, n, 5],\n                 \"y2_axis\": True, \"line\": {\"color\": \"#D4A72C\", \"width\": 2.25}, \"marker\": {\"type\": \"circle\", \"size\": 6}})\ncol.combine(line)\ncol.set_title({\"name\": \"Revenue and gross margin\"})\ncol.set_y_axis({\"name\": \"Revenue\", \"num_format\": \"#,##0,\\\"k\\\"\", \"major_gridlines\": {\"visible\": True, \"line\": {\"color\": \"#E5E7EB\"}}})\nline.set_y2_axis({\"name\": \"Margin\", \"num_format\": \"0%\", \"min\": 0.2, \"max\": 0.4})\ncol.set_legend({\"position\": \"bottom\"})\n",[14,700,701,721,789,818,836,897,956,961,975,1036,1078],{"__ignoreMap":39},[43,702,703,706,708,711,714,716,719],{"class":45,"line":46},[43,704,705],{"class":83},"col ",[43,707,127],{"class":79},[43,709,710],{"class":83}," wb.add_chart({",[43,712,713],{"class":53},"\"type\"",[43,715,488],{"class":83},[43,717,718],{"class":53},"\"column\"",[43,720,494],{"class":83},[43,722,723,726,729,732,734,736,738,740,742,745,748,750,752,754,756,758,760,763,765,767,770,772,774,776,778,780,782,784,786],{"class":45,"line":93},[43,724,725],{"class":83},"col.add_series({",[43,727,728],{"class":53},"\"name\"",[43,730,731],{"class":83},": [",[43,733,469],{"class":53},[43,735,154],{"class":83},[43,737,364],{"class":133},[43,739,154],{"class":83},[43,741,599],{"class":133},[43,743,744],{"class":83},"], ",[43,746,747],{"class":53},"\"categories\"",[43,749,731],{"class":83},[43,751,469],{"class":53},[43,753,154],{"class":83},[43,755,230],{"class":133},[43,757,154],{"class":83},[43,759,364],{"class":133},[43,761,762],{"class":83},", n, ",[43,764,364],{"class":133},[43,766,744],{"class":83},[43,768,769],{"class":53},"\"values\"",[43,771,731],{"class":83},[43,773,469],{"class":53},[43,775,154],{"class":83},[43,777,230],{"class":133},[43,779,154],{"class":83},[43,781,599],{"class":133},[43,783,762],{"class":83},[43,785,599],{"class":133},[43,787,788],{"class":83},"],\n",[43,790,791,794,797,800,802,805,808,811,813,816],{"class":45,"line":106},[43,792,793],{"class":53},"                \"fill\"",[43,795,796],{"class":83},": {",[43,798,799],{"class":53},"\"color\"",[43,801,488],{"class":83},[43,803,804],{"class":53},"\"#1F6FEB\"",[43,806,807],{"class":83},"}, ",[43,809,810],{"class":53},"\"gap\"",[43,812,488],{"class":83},[43,814,815],{"class":133},"60",[43,817,494],{"class":83},[43,819,820,823,825,827,829,831,834],{"class":45,"line":114},[43,821,822],{"class":83},"line ",[43,824,127],{"class":79},[43,826,710],{"class":83},[43,828,713],{"class":53},[43,830,488],{"class":83},[43,832,833],{"class":53},"\"line\"",[43,835,494],{"class":83},[43,837,838,841,843,845,847,849,851,853,855,857,859,861,863,865,867,869,871,873,875,877,879,881,883,885,887,889,891,893,895],{"class":45,"line":121},[43,839,840],{"class":83},"line.add_series({",[43,842,728],{"class":53},[43,844,731],{"class":83},[43,846,469],{"class":53},[43,848,154],{"class":83},[43,850,364],{"class":133},[43,852,154],{"class":83},[43,854,626],{"class":133},[43,856,744],{"class":83},[43,858,747],{"class":53},[43,860,731],{"class":83},[43,862,469],{"class":53},[43,864,154],{"class":83},[43,866,230],{"class":133},[43,868,154],{"class":83},[43,870,364],{"class":133},[43,872,762],{"class":83},[43,874,364],{"class":133},[43,876,744],{"class":83},[43,878,769],{"class":53},[43,880,731],{"class":83},[43,882,469],{"class":53},[43,884,154],{"class":83},[43,886,230],{"class":133},[43,888,154],{"class":83},[43,890,626],{"class":133},[43,892,762],{"class":83},[43,894,626],{"class":133},[43,896,788],{"class":83},[43,898,899,902,904,906,908,910,912,914,916,919,921,924,926,929,931,934,936,938,940,943,945,948,950,953],{"class":45,"line":140},[43,900,901],{"class":53},"                 \"y2_axis\"",[43,903,488],{"class":83},[43,905,491],{"class":133},[43,907,154],{"class":83},[43,909,833],{"class":53},[43,911,796],{"class":83},[43,913,799],{"class":53},[43,915,488],{"class":83},[43,917,918],{"class":53},"\"#D4A72C\"",[43,920,154],{"class":83},[43,922,923],{"class":53},"\"width\"",[43,925,488],{"class":83},[43,927,928],{"class":133},"2.25",[43,930,807],{"class":83},[43,932,933],{"class":53},"\"marker\"",[43,935,796],{"class":83},[43,937,713],{"class":53},[43,939,488],{"class":83},[43,941,942],{"class":53},"\"circle\"",[43,944,154],{"class":83},[43,946,947],{"class":53},"\"size\"",[43,949,488],{"class":83},[43,951,952],{"class":133},"6",[43,954,955],{"class":83},"}})\n",[43,957,958],{"class":45,"line":186},[43,959,960],{"class":83},"col.combine(line)\n",[43,962,963,966,968,970,973],{"class":45,"line":213},[43,964,965],{"class":83},"col.set_title({",[43,967,728],{"class":53},[43,969,488],{"class":83},[43,971,972],{"class":53},"\"Revenue and gross margin\"",[43,974,494],{"class":83},[43,976,977,980,982,984,987,989,991,993,996,999,1002,1004,1006,1008,1011,1013,1016,1018,1020,1022,1024,1026,1028,1030,1033],{"class":45,"line":279},[43,978,979],{"class":83},"col.set_y_axis({",[43,981,728],{"class":53},[43,983,488],{"class":83},[43,985,986],{"class":53},"\"Revenue\"",[43,988,154],{"class":83},[43,990,610],{"class":53},[43,992,488],{"class":83},[43,994,995],{"class":53},"\"#,##0,",[43,997,998],{"class":177},"\\\"",[43,1000,1001],{"class":53},"k",[43,1003,998],{"class":177},[43,1005,174],{"class":53},[43,1007,154],{"class":83},[43,1009,1010],{"class":53},"\"major_gridlines\"",[43,1012,796],{"class":83},[43,1014,1015],{"class":53},"\"visible\"",[43,1017,488],{"class":83},[43,1019,491],{"class":133},[43,1021,154],{"class":83},[43,1023,833],{"class":53},[43,1025,796],{"class":83},[43,1027,799],{"class":53},[43,1029,488],{"class":83},[43,1031,1032],{"class":53},"\"#E5E7EB\"",[43,1034,1035],{"class":83},"}}})\n",[43,1037,1038,1041,1043,1045,1047,1049,1051,1053,1056,1058,1061,1063,1066,1068,1071,1073,1076],{"class":45,"line":321},[43,1039,1040],{"class":83},"line.set_y2_axis({",[43,1042,728],{"class":53},[43,1044,488],{"class":83},[43,1046,396],{"class":53},[43,1048,154],{"class":83},[43,1050,610],{"class":53},[43,1052,488],{"class":83},[43,1054,1055],{"class":53},"\"0%\"",[43,1057,154],{"class":83},[43,1059,1060],{"class":53},"\"min\"",[43,1062,488],{"class":83},[43,1064,1065],{"class":133},"0.2",[43,1067,154],{"class":83},[43,1069,1070],{"class":53},"\"max\"",[43,1072,488],{"class":83},[43,1074,1075],{"class":133},"0.4",[43,1077,494],{"class":83},[43,1079,1080,1083,1086,1088,1091],{"class":45,"line":401},[43,1081,1082],{"class":83},"col.set_legend({",[43,1084,1085],{"class":53},"\"position\"",[43,1087,488],{"class":83},[43,1089,1090],{"class":53},"\"bottom\"",[43,1092,494],{"class":83},[10,1094,1095,1096,1100,1101,1104,1105,1107,1108,1111,1112,1115,1116,27],{},"The ",[1097,1098,1099],"em",{},"primary"," chart (the columns) owns the title, the category axis and the legend; the secondary chart's series join it. ",[14,1102,1103],{},"y2_axis: True"," on the line series is what moves it to its own scale on the right, and the secondary axis is configured on the ",[1097,1106,45],{}," chart with ",[14,1109,1110],{},"set_y2_axis()",". Fixing that axis to 20–40% stops Excel from starting it at zero, which would flatten a margin that moves between 28% and 35% into an almost straight line — and that movement is the story here: revenue grew steadily from 317k to 391k while margin peaked at 34.7% in February and slid to 28% by July. The ",[14,1113,1114],{},"#,##0,\"k\""," format on the primary axis shows revenue in thousands — the trailing comma divides by 1,000. The openpyxl version of the same chart is in ",[23,1117,1119],{"href":1118},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002Fadd-a-combo-chart-with-a-secondary-axis-in-openpyxl\u002F","Add a Combo Chart with a Secondary Axis in openpyxl",[1121,1122,1130,1131,1130,1135,1130,1139,1130,1145,1130,1152,1130,1158,1130,1162,1130,1166,1130,1169,1130,1173,1130,1176,1130,1180,1130,1183,1130,1187,1130,1191,1130,1197,1130,1201,1130,1205,1130,1209,1130,1213,1130,1217,1130,1221,1130,1225,1130,1229,1130,1233,1130,1237,1130,1241,1130,1248,1130,1254,1130,1257,1130,1260,1130,1263,1130,1266,1130,1269,1130,1272,1130,1274,1130,1276,1130,1279,1130,1282],"svg",{"viewBox":1123,"role":1124,"ariaLabelledBy":1125,"xmlns":1128,"style":1129},"4 0 748 252","img",[1126,1127],"cx-combo-t","cx-combo-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:748px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[1132,1133,1134],"title",{"id":1126},"The revenue columns of the combined chart",[1136,1137,1138],"desc",{"id":1127},"Monthly total revenue rises from 317 thousand in October 2025 to 391 thousand in September 2026, shown as columns on the left axis. Gross margin peaks at 34.7 percent in February and falls to 28.0 percent in July, shown as a line on the right axis scaled from 20 to 40 percent.",[1140,1141],"rect",{"x":599,"y":364,"width":1142,"height":1143,"fill":1144},"748","252","#ffffff",[45,1146],{"x1":1147,"y1":1148,"x2":1149,"y2":1148,"stroke":1150,"style":1151},"54.0","214.0","736.0","var(--line,#cdd5e6)","stroke-width:1px",[1153,1154,364],"text",{"x":1155,"y":1156,"style":1157},"31.0","218.0","font-size:11px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle",[45,1159],{"x1":1147,"y1":1160,"x2":1149,"y2":1160,"stroke":1150,"style":1161},"166.5","stroke-width:1px;stroke-dasharray:5 4",[1153,1163,1165],{"x":1155,"y":1164,"style":1157},"170.5","100",[45,1167],{"x1":1147,"y1":1168,"x2":1149,"y2":1168,"stroke":1150,"style":1161},"119.0",[1153,1170,1172],{"x":1155,"y":1171,"style":1157},"123.0","200",[45,1174],{"x1":1147,"y1":1175,"x2":1149,"y2":1175,"stroke":1150,"style":1161},"71.5",[1153,1177,1179],{"x":1155,"y":1178,"style":1157},"75.5","300",[45,1181],{"x1":1147,"y1":1182,"x2":1149,"y2":1182,"stroke":1150,"style":1161},"24.0",[1153,1184,1186],{"x":1155,"y":1185,"style":1157},"28.0","400",[45,1188],{"x1":1147,"y1":1148,"x2":1149,"y2":1148,"stroke":1189,"style":1190},"var(--muted,#5b6780)","stroke-width:1.5px",[1153,1192,1196],{"x":1193,"y":1194,"style":1195},"82.5","232.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","Oct",[1153,1198,1200],{"x":1199,"y":1194,"style":1195},"139.3","Nov",[1153,1202,1204],{"x":1203,"y":1194,"style":1195},"196.1","Dec",[1153,1206,1208],{"x":1207,"y":1194,"style":1195},"252.9","Jan",[1153,1210,1212],{"x":1211,"y":1194,"style":1195},"309.8","Feb",[1153,1214,1216],{"x":1215,"y":1194,"style":1195},"366.6","Mar",[1153,1218,1220],{"x":1219,"y":1194,"style":1195},"423.4","Apr",[1153,1222,1224],{"x":1223,"y":1194,"style":1195},"480.3","May",[1153,1226,1228],{"x":1227,"y":1194,"style":1195},"537.1","Jun",[1153,1230,1232],{"x":1231,"y":1194,"style":1195},"593.9","Jul",[1153,1234,1236],{"x":1235,"y":1194,"style":1195},"650.8","Aug",[1153,1238,1240],{"x":1239,"y":1194,"style":1195},"707.6","Sep",[1242,1243],"path",{"d":1244,"fill":1245,"stroke":1246,"style":1247},"M82.5,63.4 L139.3,47.8 L196.1,49.7 L252.9,41.6 L309.8,36.8 L366.6,40.2 L423.4,35.4 L480.3,35.4 L537.1,35.4 L593.9,31.6 L650.8,32.6 L707.6,28.3","none","var(--brand,#5b5cf0)","stroke-width:2.5px;stroke-linejoin:round;stroke-linecap:round",[1249,1250],"circle",{"cx":1193,"cy":1251,"r":1252,"fill":1144,"stroke":1246,"style":1253},"63.4","4.0","stroke-width:2px",[1249,1255],{"cx":1199,"cy":1256,"r":1252,"fill":1144,"stroke":1246,"style":1253},"47.8",[1249,1258],{"cx":1203,"cy":1259,"r":1252,"fill":1144,"stroke":1246,"style":1253},"49.7",[1249,1261],{"cx":1207,"cy":1262,"r":1252,"fill":1144,"stroke":1246,"style":1253},"41.6",[1249,1264],{"cx":1211,"cy":1265,"r":1252,"fill":1144,"stroke":1246,"style":1253},"36.8",[1249,1267],{"cx":1215,"cy":1268,"r":1252,"fill":1144,"stroke":1246,"style":1253},"40.2",[1249,1270],{"cx":1219,"cy":1271,"r":1252,"fill":1144,"stroke":1246,"style":1253},"35.4",[1249,1273],{"cx":1223,"cy":1271,"r":1252,"fill":1144,"stroke":1246,"style":1253},[1249,1275],{"cx":1227,"cy":1271,"r":1252,"fill":1144,"stroke":1246,"style":1253},[1249,1277],{"cx":1231,"cy":1278,"r":1252,"fill":1144,"stroke":1246,"style":1253},"31.6",[1249,1280],{"cx":1235,"cy":1281,"r":1252,"fill":1144,"stroke":1246,"style":1253},"32.6",[1249,1283],{"cx":1239,"cy":1284,"r":1252,"fill":1144,"stroke":1246,"style":1253},"28.3",[29,1286,1288],{"id":1287},"step-3-stacked-columns-with-a-total-line","Step 3 — Stacked columns with a total line",[10,1290,1291,1292,1295],{},"A stacked column chart shows how each product line contributes; adding the total as a line on the ",[1097,1293,1294],{},"same"," axis puts a marker on top of each stack:",[34,1297,1299],{"className":70,"code":1298,"language":72,"meta":39,"style":39},"stack = wb.add_chart({\"type\": \"column\", \"subtype\": \"stacked\"})\ncolours = [\"#1F6FEB\", \"#3FB950\", \"#A371F7\"]\nfor c, colour in zip(range(1, 4), colours):\n    stack.add_series({\"name\": [\"Data\", 0, c], \"categories\": [\"Data\", 1, 0, n, 0], \"values\": [\"Data\", 1, c, n, c],\n                      \"fill\": {\"color\": colour}, \"gap\": 50})\ntotal = wb.add_chart({\"type\": \"line\"})\ntotal.add_series({\"name\": [\"Data\", 0, 4], \"categories\": [\"Data\", 1, 0, n, 0], \"values\": [\"Data\", 1, 4, n, 4],\n                  \"line\": {\"none\": True}, \"marker\": {\"type\": \"diamond\", \"size\": 7, \"fill\": {\"color\": \"#24292F\"}},\n                  \"data_labels\": {\"value\": True, \"position\": \"above\", \"num_format\": \"#,##0,\\\"k\\\"\"}})\nstack.combine(total)\nstack.set_title({\"name\": \"Revenue by product line\"})\nstack.set_y_axis({\"num_format\": \"#,##0,\\\"k\\\"\"})\nstack.set_legend({\"position\": \"bottom\"})\n",[14,1300,1301,1328,1351,1379,1430,1451,1468,1529,1582,1623,1628,1642,1663],{"__ignoreMap":39},[43,1302,1303,1306,1308,1310,1312,1314,1316,1318,1321,1323,1326],{"class":45,"line":46},[43,1304,1305],{"class":83},"stack ",[43,1307,127],{"class":79},[43,1309,710],{"class":83},[43,1311,713],{"class":53},[43,1313,488],{"class":83},[43,1315,718],{"class":53},[43,1317,154],{"class":83},[43,1319,1320],{"class":53},"\"subtype\"",[43,1322,488],{"class":83},[43,1324,1325],{"class":53},"\"stacked\"",[43,1327,494],{"class":83},[43,1329,1330,1333,1335,1337,1339,1341,1344,1346,1349],{"class":45,"line":93},[43,1331,1332],{"class":83},"colours ",[43,1334,127],{"class":79},[43,1336,194],{"class":83},[43,1338,804],{"class":53},[43,1340,154],{"class":83},[43,1342,1343],{"class":53},"\"#3FB950\"",[43,1345,154],{"class":83},[43,1347,1348],{"class":53},"\"#A371F7\"",[43,1350,210],{"class":83},[43,1352,1353,1355,1358,1360,1362,1365,1368,1370,1372,1374,1376],{"class":45,"line":106},[43,1354,525],{"class":79},[43,1356,1357],{"class":83}," c, colour ",[43,1359,288],{"class":79},[43,1361,291],{"class":133},[43,1363,1364],{"class":83},"(",[43,1366,1367],{"class":133},"range",[43,1369,1364],{"class":83},[43,1371,230],{"class":133},[43,1373,154],{"class":83},[43,1375,599],{"class":133},[43,1377,1378],{"class":83},"), colours):\n",[43,1380,1381,1384,1386,1388,1390,1392,1394,1397,1399,1401,1403,1405,1407,1409,1411,1413,1415,1417,1419,1421,1423,1425,1427],{"class":45,"line":114},[43,1382,1383],{"class":83},"    stack.add_series({",[43,1385,728],{"class":53},[43,1387,731],{"class":83},[43,1389,469],{"class":53},[43,1391,154],{"class":83},[43,1393,364],{"class":133},[43,1395,1396],{"class":83},", c], ",[43,1398,747],{"class":53},[43,1400,731],{"class":83},[43,1402,469],{"class":53},[43,1404,154],{"class":83},[43,1406,230],{"class":133},[43,1408,154],{"class":83},[43,1410,364],{"class":133},[43,1412,762],{"class":83},[43,1414,364],{"class":133},[43,1416,744],{"class":83},[43,1418,769],{"class":53},[43,1420,731],{"class":83},[43,1422,469],{"class":53},[43,1424,154],{"class":83},[43,1426,230],{"class":133},[43,1428,1429],{"class":83},", c, n, c],\n",[43,1431,1432,1435,1437,1439,1442,1444,1446,1449],{"class":45,"line":121},[43,1433,1434],{"class":53},"                      \"fill\"",[43,1436,796],{"class":83},[43,1438,799],{"class":53},[43,1440,1441],{"class":83},": colour}, ",[43,1443,810],{"class":53},[43,1445,488],{"class":83},[43,1447,1448],{"class":133},"50",[43,1450,494],{"class":83},[43,1452,1453,1456,1458,1460,1462,1464,1466],{"class":45,"line":140},[43,1454,1455],{"class":83},"total ",[43,1457,127],{"class":79},[43,1459,710],{"class":83},[43,1461,713],{"class":53},[43,1463,488],{"class":83},[43,1465,833],{"class":53},[43,1467,494],{"class":83},[43,1469,1470,1473,1475,1477,1479,1481,1483,1485,1487,1489,1491,1493,1495,1497,1499,1501,1503,1505,1507,1509,1511,1513,1515,1517,1519,1521,1523,1525,1527],{"class":45,"line":186},[43,1471,1472],{"class":83},"total.add_series({",[43,1474,728],{"class":53},[43,1476,731],{"class":83},[43,1478,469],{"class":53},[43,1480,154],{"class":83},[43,1482,364],{"class":133},[43,1484,154],{"class":83},[43,1486,599],{"class":133},[43,1488,744],{"class":83},[43,1490,747],{"class":53},[43,1492,731],{"class":83},[43,1494,469],{"class":53},[43,1496,154],{"class":83},[43,1498,230],{"class":133},[43,1500,154],{"class":83},[43,1502,364],{"class":133},[43,1504,762],{"class":83},[43,1506,364],{"class":133},[43,1508,744],{"class":83},[43,1510,769],{"class":53},[43,1512,731],{"class":83},[43,1514,469],{"class":53},[43,1516,154],{"class":83},[43,1518,230],{"class":133},[43,1520,154],{"class":83},[43,1522,599],{"class":133},[43,1524,762],{"class":83},[43,1526,599],{"class":133},[43,1528,788],{"class":83},[43,1530,1531,1534,1536,1539,1541,1543,1545,1547,1549,1551,1553,1556,1558,1560,1562,1565,1567,1570,1572,1574,1576,1579],{"class":45,"line":213},[43,1532,1533],{"class":53},"                  \"line\"",[43,1535,796],{"class":83},[43,1537,1538],{"class":53},"\"none\"",[43,1540,488],{"class":83},[43,1542,491],{"class":133},[43,1544,807],{"class":83},[43,1546,933],{"class":53},[43,1548,796],{"class":83},[43,1550,713],{"class":53},[43,1552,488],{"class":83},[43,1554,1555],{"class":53},"\"diamond\"",[43,1557,154],{"class":83},[43,1559,947],{"class":53},[43,1561,488],{"class":83},[43,1563,1564],{"class":133},"7",[43,1566,154],{"class":83},[43,1568,1569],{"class":53},"\"fill\"",[43,1571,796],{"class":83},[43,1573,799],{"class":53},[43,1575,488],{"class":83},[43,1577,1578],{"class":53},"\"#24292F\"",[43,1580,1581],{"class":83},"}},\n",[43,1583,1584,1587,1589,1592,1594,1596,1598,1600,1602,1605,1607,1609,1611,1613,1615,1617,1619,1621],{"class":45,"line":279},[43,1585,1586],{"class":53},"                  \"data_labels\"",[43,1588,796],{"class":83},[43,1590,1591],{"class":53},"\"value\"",[43,1593,488],{"class":83},[43,1595,491],{"class":133},[43,1597,154],{"class":83},[43,1599,1085],{"class":53},[43,1601,488],{"class":83},[43,1603,1604],{"class":53},"\"above\"",[43,1606,154],{"class":83},[43,1608,610],{"class":53},[43,1610,488],{"class":83},[43,1612,995],{"class":53},[43,1614,998],{"class":177},[43,1616,1001],{"class":53},[43,1618,998],{"class":177},[43,1620,174],{"class":53},[43,1622,955],{"class":83},[43,1624,1625],{"class":45,"line":321},[43,1626,1627],{"class":83},"stack.combine(total)\n",[43,1629,1630,1633,1635,1637,1640],{"class":45,"line":401},[43,1631,1632],{"class":83},"stack.set_title({",[43,1634,728],{"class":53},[43,1636,488],{"class":83},[43,1638,1639],{"class":53},"\"Revenue by product line\"",[43,1641,494],{"class":83},[43,1643,1644,1647,1649,1651,1653,1655,1657,1659,1661],{"class":45,"line":437},[43,1645,1646],{"class":83},"stack.set_y_axis({",[43,1648,610],{"class":53},[43,1650,488],{"class":83},[43,1652,995],{"class":53},[43,1654,998],{"class":177},[43,1656,1001],{"class":53},[43,1658,998],{"class":177},[43,1660,174],{"class":53},[43,1662,494],{"class":83},[43,1664,1665,1668,1670,1672,1674],{"class":45,"line":442},[43,1666,1667],{"class":83},"stack.set_legend({",[43,1669,1085],{"class":53},[43,1671,488],{"class":83},[43,1673,1090],{"class":53},[43,1675,494],{"class":83},[10,1677,1678,1679,1681,1682,1685],{},"Here the line series has no ",[14,1680,690],{},", so it shares the columns' scale and each diamond sits exactly on top of its stack; hiding the line itself (",[14,1683,1684],{},"\"line\": {\"none\": True}",") leaves just the markers with their labels. This is the standard way to label stack totals, which Excel's stacked column chart does not do on its own.",[1121,1687,1130,1693,1130,1696,1130,1699,1130,1703,1130,1712,1130,1721,1130,1727,1130,1732,1130,1737,1130,1741,1130,1745,1130,1749,1130,1754,1130,1761,1130,1766,1130,1770,1130,1773,1130,1776,1130,1779],{"viewBox":1688,"role":1124,"ariaLabelledBy":1689,"xmlns":1128,"style":1692},"4 0 752 233",[1690,1691],"cx-axes-t","cx-axes-d","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[1132,1694,1695],{"id":1690},"Secondary axis or shared axis",[1136,1697,1698],{"id":1691},"Put the second series on a secondary axis when it measures something different, such as a percentage beside revenue. Keep it on the same axis when it is in the same units, such as a total line over stacked columns, so its markers align with the stacks.",[1140,1700],{"x":599,"y":364,"width":1701,"height":1702,"fill":1144},"752","233",[1140,1704],{"x":1705,"y":1706,"width":1707,"height":1708,"rx":1709,"fill":1710,"stroke":1711,"style":1253},"20.0","16.0","351.0","201.0","14","#fdefd8","var(--gold,#b4740a)",[1713,1714,1716],"g",{"transform":1715},"translate(182.5,29.0) scale(1.083)",[1242,1717],{"d":1718,"fill":1245,"stroke":1719,"style":1720},"M4 20h16 M4 20V4 M6 16l4-5 4 3 6-7","var(--gold-ink,#7a4e06)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[1153,1722,1726],{"x":1723,"y":1724,"style":1725},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Secondary axis (y2_axis)",[45,1728],{"x1":1729,"y1":1730,"x2":1731,"y2":1730,"stroke":1711,"style":1151},"36.0","91.0","355.0",[1153,1733,1736],{"x":1723,"y":1734,"style":1735},"111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","different units or scale",[1153,1738,1740],{"x":1723,"y":1739,"style":1735},"137.0","e.g. margin % beside revenue",[1153,1742,1744],{"x":1723,"y":1743,"style":1735},"163.0","own scale on the right",[1153,1746,1748],{"x":1723,"y":1747,"style":1735},"189.0","set with set_y2_axis",[1140,1750],{"x":1751,"y":1706,"width":1707,"height":1708,"rx":1709,"fill":1752,"stroke":1753,"style":1253},"389.0","#d9f4f1","var(--teal,#0f9488)",[1713,1755,1757],{"transform":1756},"translate(551.5,29.0) scale(1.083)",[1242,1758],{"d":1759,"fill":1245,"stroke":1760,"style":1720},"M4 20h16 M7 17v-5 M12 17V7 M17 17v-8","var(--teal-ink,#0b6157)",[1153,1762,1765],{"x":1763,"y":1724,"style":1764},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Shared axis",[45,1767],{"x1":1768,"y1":1730,"x2":1769,"y2":1730,"stroke":1753,"style":1151},"405.0","724.0",[1153,1771,1772],{"x":1763,"y":1734,"style":1735},"same units",[1153,1774,1775],{"x":1763,"y":1739,"style":1735},"e.g. total over stacked columns",[1153,1777,1778],{"x":1763,"y":1743,"style":1735},"markers sit on the stacks",[1153,1780,1781],{"x":1763,"y":1747,"style":1735},"no y2_axis option",[1121,1783,1130,1788,1130,1791,1130,1794,1130,1797,1130,1802,1130,1810,1130,1816,1130,1820,1130,1824,1130,1829,1130,1834,1130,1838,1130,1844,1130,1849,1130,1853,1130,1857,1130,1861,1130,1865,1130,1868,1130,1871,1130,1876,1130,1881,1130,1883,1130,1887,1130,1890,1130,1893,1130,1899,1130,1903,1130,1906,1130,1909,1130,1913,1130,1916,1130,1919,1130,1925,1130,1929,1130,1932],{"viewBox":1784,"role":1124,"ariaLabelledBy":1785,"xmlns":1128,"style":1692},"4 0 752 160",[1786,1787],"cx-build-t","cx-build-d",[1132,1789,1790],{"id":1786},"Building a combined chart",[1136,1792,1793],{"id":1787},"Write the data to a sheet, create the primary column chart and the secondary line chart, mark the line series for the secondary axis, configure both axes, combine the line into the column chart, and place the combined chart once, on a worksheet or a chartsheet.",[1140,1795],{"x":599,"y":364,"width":1701,"height":1796,"fill":1144},"160",[1140,1798],{"x":1705,"y":1706,"width":1799,"height":1800,"rx":245,"fill":1801,"stroke":1150,"style":1253},"115.2","128.0","#e7ebef",[1713,1803,1805],{"transform":1804},"translate(65.6,37.8) scale(1.000)",[1242,1806],{"d":1807,"fill":1245,"stroke":1808,"style":1809},"M3 5h18v14H3z M3 10h18 M3 15h18 M9 5v14","var(--text,#172033)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[1153,1811,1815],{"x":1812,"y":1813,"style":1814},"77.6","84.2","font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Data sheet",[1153,1817,1819],{"x":1812,"y":1818,"style":1195},"103.8","charts read",[1153,1821,1823],{"x":1812,"y":1822,"style":1195},"121.2","cells",[45,1825],{"x1":1826,"y1":1827,"x2":1828,"y2":1827,"stroke":1246,"style":1253},"140.2","80.0","162.2",[1830,1831],"polygon",{"points":1832,"fill":1833},"166.2,80.0 157.2,85.0 157.2,75.0","#5b5cf0",[1140,1835],{"x":1836,"y":1706,"width":1799,"height":1800,"rx":245,"fill":1837,"stroke":1246,"style":1253},"171.2","#f0f4ff",[1713,1839,1841],{"transform":1840},"translate(216.8,29.0) scale(1.000)",[1242,1842],{"d":1759,"fill":1245,"stroke":1843,"style":1809},"var(--brand-strong,#4338ca)",[1153,1845,1848],{"x":1846,"y":1178,"style":1847},"228.8","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Column",[1153,1850,1852],{"x":1846,"y":1851,"style":1847},"93.0","chart",[1153,1854,1856],{"x":1846,"y":1855,"style":1195},"112.5","primary, owns",[1153,1858,1860],{"x":1846,"y":1859,"style":1195},"130.0","title and legend",[45,1862],{"x1":1863,"y1":1827,"x2":1864,"y2":1827,"stroke":1246,"style":1253},"291.4","313.4",[1830,1866],{"points":1867,"fill":1833},"317.4,80.0 308.4,85.0 308.4,75.0",[1140,1869],{"x":1870,"y":1706,"width":1799,"height":1800,"rx":245,"fill":1710,"stroke":1711,"style":1253},"322.4",[1713,1872,1874],{"transform":1873},"translate(368.0,46.5) scale(1.000)",[1242,1875],{"d":1718,"fill":1245,"stroke":1719,"style":1809},[1153,1877,1880],{"x":1878,"y":1851,"style":1879},"380.0","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Line chart",[1153,1882,1103],{"x":1878,"y":1855,"style":1195},[45,1884],{"x1":1885,"y1":1827,"x2":1886,"y2":1827,"stroke":1246,"style":1253},"442.6","464.6",[1830,1888],{"points":1889,"fill":1833},"468.6,80.0 459.6,85.0 459.6,75.0",[1140,1891],{"x":1892,"y":1706,"width":1799,"height":1800,"rx":245,"fill":1752,"stroke":1753,"style":1253},"473.6",[1713,1894,1896],{"transform":1895},"translate(519.2,37.8) scale(1.000)",[1242,1897],{"d":1898,"fill":1245,"stroke":1760,"style":1809},"M6 4v5a5 5 0 0 0 5 5h7 M6 20v-5 M15 11l3 3-3 3",[1153,1900,694],{"x":1901,"y":1813,"style":1902},"531.2","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle",[1153,1904,1905],{"x":1901,"y":1818,"style":1195},"line joins",[1153,1907,1908],{"x":1901,"y":1822,"style":1195},"columns",[45,1910],{"x1":1911,"y1":1827,"x2":1912,"y2":1827,"stroke":1246,"style":1253},"593.8","615.8",[1830,1914],{"points":1915,"fill":1833},"619.8,80.0 610.8,85.0 610.8,75.0",[1140,1917],{"x":1918,"y":1706,"width":1799,"height":1800,"rx":245,"fill":1801,"stroke":1150,"style":1253},"624.8",[1713,1920,1922],{"transform":1921},"translate(670.4,37.8) scale(1.000)",[1242,1923],{"d":1924,"fill":1245,"stroke":1808,"style":1809},"M12 3l9 5-9 5-9-5z M3 13l9 5 9-5 M3 17l9 5 9-5",[1153,1926,1928],{"x":1927,"y":1813,"style":1814},"682.4","Place once",[1153,1930,1931],{"x":1927,"y":1818,"style":1195},"worksheet or",[1153,1933,1934],{"x":1927,"y":1822,"style":1195},"chartsheet",[29,1936,1938],{"id":1937},"step-4-chartsheets-and-checking-the-result","Step 4 — Chartsheets, and checking the result",[10,1940,1941],{},"A chartsheet is a tab that contains only a chart, sized to fill the window and the printed page:",[34,1943,1945],{"className":70,"code":1944,"language":72,"meta":39,"style":39},"for name, chart in [(\"Revenue & margin\", col), (\"By product line\", stack)]:\n    cs = wb.add_chartsheet(name)\n    cs.set_chart(chart)\n    cs.set_landscape()\nwb.close()\n",[14,1946,1947,1971,1981,1986,1991],{"__ignoreMap":39},[43,1948,1949,1951,1954,1956,1959,1962,1965,1968],{"class":45,"line":46},[43,1950,525],{"class":79},[43,1952,1953],{"class":83}," name, chart ",[43,1955,288],{"class":79},[43,1957,1958],{"class":83}," [(",[43,1960,1961],{"class":53},"\"Revenue & margin\"",[43,1963,1964],{"class":83},", col), (",[43,1966,1967],{"class":53},"\"By product line\"",[43,1969,1970],{"class":83},", stack)]:\n",[43,1972,1973,1976,1978],{"class":45,"line":93},[43,1974,1975],{"class":83},"    cs ",[43,1977,127],{"class":79},[43,1979,1980],{"class":83}," wb.add_chartsheet(name)\n",[43,1982,1983],{"class":45,"line":106},[43,1984,1985],{"class":83},"    cs.set_chart(chart)\n",[43,1987,1988],{"class":45,"line":114},[43,1989,1990],{"class":83},"    cs.set_landscape()\n",[43,1992,1993],{"class":45,"line":121},[43,1994,1995],{"class":83},"wb.close()\n",[10,1997,1998,1999,2002,2003,2006,2007,2010],{},"A chartsheet has no cells, so it cannot hold the chart's data; the chart keeps reading from the ",[1097,2000,2001],{},"Data"," sheet, which is why that sheet must stay in the workbook even if it is hidden. Each chart can be placed only once — either inserted into a worksheet with ",[14,2004,2005],{},"insert_chart()"," or set on a chartsheet — so a chart object belongs to exactly one location. Chartsheets appear as tabs in the order they are added; adding the data sheet first, as here, keeps it as the first tab, and many reports then hide it with ",[14,2008,2009],{},"data.hide()"," so readers see only the charts. Charts are XML definitions that Excel renders when the file is opened; nothing in Python renders them, so check the definitions themselves:",[34,2012,2014],{"className":70,"code":2013,"language":72,"meta":39,"style":39},"import html, re, zipfile\n\nwith zipfile.ZipFile(\"charts.xlsx\") as z:\n    names = z.namelist()\n    sheets = [html.unescape(t) for t in re.findall(r'\u003Csheet name=\"([^\"]+)\"', z.read(\"xl\u002Fworkbook.xml\").decode())]\n    charts = sorted(n for n in names if re.match(r\"xl\u002Fcharts\u002Fchart\\d+\\.xml\", n))\n    print(\"tabs:\", sheets, \"| chartsheets:\", sum(n.startswith(\"xl\u002Fchartsheets\u002Fsheet\") for n in names))\n    for c in charts:\n        xml = z.read(c).decode()\n        kinds = re.findall(r\"\u003Cc:(barChart|lineChart)>\", xml)\n        print(c, kinds, \"| axes:\", len(re.findall(r\"\u003Cc:valAx>\", xml)), \"| refs:\", sorted(set(re.findall(r\"Data!\\$[A-F]\\$\", xml))))\n",[14,2015,2016,2023,2027,2044,2054,2108,2157,2195,2208,2218,2251],{"__ignoreMap":39},[43,2017,2018,2020],{"class":45,"line":46},[43,2019,80],{"class":79},[43,2021,2022],{"class":83}," html, re, zipfile\n",[43,2024,2025],{"class":45,"line":93},[43,2026,118],{"emptyLinePlaceholder":117},[43,2028,2029,2032,2035,2037,2039,2041],{"class":45,"line":106},[43,2030,2031],{"class":79},"with",[43,2033,2034],{"class":83}," zipfile.ZipFile(",[43,2036,453],{"class":53},[43,2038,347],{"class":83},[43,2040,87],{"class":79},[43,2042,2043],{"class":83}," z:\n",[43,2045,2046,2049,2051],{"class":45,"line":114},[43,2047,2048],{"class":83},"    names ",[43,2050,127],{"class":79},[43,2052,2053],{"class":83}," z.namelist()\n",[43,2055,2056,2059,2061,2064,2066,2069,2071,2074,2077,2080,2083,2086,2088,2091,2093,2096,2099,2102,2105],{"class":45,"line":121},[43,2057,2058],{"class":83},"    sheets ",[43,2060,127],{"class":79},[43,2062,2063],{"class":83}," [html.unescape(t) ",[43,2065,525],{"class":79},[43,2067,2068],{"class":83}," t ",[43,2070,288],{"class":79},[43,2072,2073],{"class":83}," re.findall(",[43,2075,2076],{"class":79},"r",[43,2078,2079],{"class":53},"'\u003Csheet name=\"",[43,2081,2082],{"class":133},"([",[43,2084,2085],{"class":79},"^",[43,2087,174],{"class":177},[43,2089,2090],{"class":133},"]",[43,2092,358],{"class":79},[43,2094,2095],{"class":133},")",[43,2097,2098],{"class":53},"\"'",[43,2100,2101],{"class":83},", z.read(",[43,2103,2104],{"class":53},"\"xl\u002Fworkbook.xml\"",[43,2106,2107],{"class":83},").decode())]\n",[43,2109,2110,2113,2115,2118,2121,2123,2126,2128,2131,2134,2137,2139,2142,2145,2147,2151,2154],{"class":45,"line":140},[43,2111,2112],{"class":83},"    charts ",[43,2114,127],{"class":79},[43,2116,2117],{"class":133}," sorted",[43,2119,2120],{"class":83},"(n ",[43,2122,525],{"class":79},[43,2124,2125],{"class":83}," n ",[43,2127,288],{"class":79},[43,2129,2130],{"class":83}," names ",[43,2132,2133],{"class":79},"if",[43,2135,2136],{"class":83}," re.match(",[43,2138,2076],{"class":79},[43,2140,2141],{"class":53},"\"xl\u002Fcharts\u002Fchart",[43,2143,2144],{"class":133},"\\d",[43,2146,358],{"class":79},[43,2148,2150],{"class":2149},"s_b0D","\\.",[43,2152,2153],{"class":53},"xml\"",[43,2155,2156],{"class":83},", n))\n",[43,2158,2159,2162,2164,2167,2170,2173,2175,2178,2181,2184,2186,2188,2190,2192],{"class":45,"line":186},[43,2160,2161],{"class":133},"    print",[43,2163,1364],{"class":83},[43,2165,2166],{"class":53},"\"tabs:\"",[43,2168,2169],{"class":83},", sheets, ",[43,2171,2172],{"class":53},"\"| chartsheets:\"",[43,2174,154],{"class":83},[43,2176,2177],{"class":133},"sum",[43,2179,2180],{"class":83},"(n.startswith(",[43,2182,2183],{"class":53},"\"xl\u002Fchartsheets\u002Fsheet\"",[43,2185,347],{"class":83},[43,2187,525],{"class":79},[43,2189,2125],{"class":83},[43,2191,288],{"class":79},[43,2193,2194],{"class":83}," names))\n",[43,2196,2197,2200,2203,2205],{"class":45,"line":213},[43,2198,2199],{"class":79},"    for",[43,2201,2202],{"class":83}," c ",[43,2204,288],{"class":79},[43,2206,2207],{"class":83}," charts:\n",[43,2209,2210,2213,2215],{"class":45,"line":279},[43,2211,2212],{"class":83},"        xml ",[43,2214,127],{"class":79},[43,2216,2217],{"class":83}," z.read(c).decode()\n",[43,2219,2220,2223,2225,2227,2229,2232,2234,2237,2240,2243,2245,2248],{"class":45,"line":321},[43,2221,2222],{"class":83},"        kinds ",[43,2224,127],{"class":79},[43,2226,2073],{"class":83},[43,2228,2076],{"class":79},[43,2230,2231],{"class":53},"\"\u003Cc:",[43,2233,1364],{"class":133},[43,2235,2236],{"class":53},"barChart",[43,2238,2239],{"class":79},"|",[43,2241,2242],{"class":53},"lineChart",[43,2244,2095],{"class":133},[43,2246,2247],{"class":53},">\"",[43,2249,2250],{"class":83},", xml)\n",[43,2252,2253,2256,2259,2262,2264,2267,2270,2272,2275,2278,2281,2283,2286,2288,2291,2293,2295,2298,2301,2304,2307,2309,2311,2313],{"class":45,"line":401},[43,2254,2255],{"class":133},"        print",[43,2257,2258],{"class":83},"(c, kinds, ",[43,2260,2261],{"class":53},"\"| axes:\"",[43,2263,154],{"class":83},[43,2265,2266],{"class":133},"len",[43,2268,2269],{"class":83},"(re.findall(",[43,2271,2076],{"class":79},[43,2273,2274],{"class":53},"\"\u003Cc:valAx>\"",[43,2276,2277],{"class":83},", xml)), ",[43,2279,2280],{"class":53},"\"| refs:\"",[43,2282,154],{"class":83},[43,2284,2285],{"class":133},"sorted",[43,2287,1364],{"class":83},[43,2289,2290],{"class":133},"set",[43,2292,2269],{"class":83},[43,2294,2076],{"class":79},[43,2296,2297],{"class":53},"\"Data!",[43,2299,2300],{"class":2149},"\\$",[43,2302,2303],{"class":133},"[",[43,2305,2306],{"class":177},"A-F",[43,2308,2090],{"class":133},[43,2310,2300],{"class":2149},[43,2312,174],{"class":53},[43,2314,2315],{"class":83},", xml))))\n",[10,2317,2318,2319,27],{},"The workbook has three tabs — the data and two chartsheets. The first chart contains a bar (column) chart and a line chart with two value axes, the second a bar chart and a line chart sharing one; the references show which data columns each chart reads. A check like this in a test catches the mistakes that otherwise show up only when someone opens the file: a series pointing at the wrong column, a secondary axis that was never created, a chart placed nowhere. For opening the file on Linux to look at it, export the chartsheets to PDF as in ",[23,2320,2322],{"href":2321},"\u002Fautomating-reporting-workflows\u002Fexporting-excel-reports-to-pdf\u002Fconvert-excel-to-pdf-on-linux-with-libreoffice\u002F","Convert Excel to PDF on Linux with LibreOffice",[29,2324,2326],{"id":2325},"common-pitfalls","Common pitfalls",[2328,2329,2330,2341,2350,2364,2370],"ul",{},[2331,2332,2333,2337,2338,2340],"li",{},[2334,2335,2336],"strong",{},"Configuring the secondary axis on the primary chart."," Call ",[14,2339,1110],{}," on the chart that was combined in.",[2331,2342,2343,2346,2347,2349],{},[2334,2344,2345],{},"Percentages on the revenue axis."," Put them on ",[14,2348,690],{}," with their own number format.",[2331,2351,2352,2355,2356,2359,2360,2363],{},[2334,2353,2354],{},"A secondary axis starting at zero."," Set ",[14,2357,2358],{},"min"," and ",[14,2361,2362],{},"max"," so the line's movement is visible.",[2331,2365,2366,2369],{},[2334,2367,2368],{},"Using one chart twice."," Each chart object can be inserted or set on a chartsheet once.",[2331,2371,2372,2375],{},[2334,2373,2374],{},"Expecting Python to draw the chart."," Validate the XML or render with an office application.",[29,2377,2379],{"id":2378},"conclusion","Conclusion",[10,2381,2382,2383,2385,2386,2388,2389,2392,2393,2359,2395,2398],{},"To combine chart types with XlsxWriter, build each chart separately, mark a series with ",[14,2384,1103],{}," when it needs its own scale, configure that axis with ",[14,2387,1110],{}," on the secondary chart, and merge with ",[14,2390,2391],{},"primary.combine(secondary)",". Keep a total line on the shared axis to label stacked columns, place finished charts on their own tabs with ",[14,2394,20],{},[14,2396,2397],{},"set_chart()",", and check the chart XML in tests because nothing in Python renders the charts.",[29,2400,2402],{"id":2401},"frequently-asked-questions","Frequently asked questions",[10,2404,2405,2408],{},[2334,2406,2407],{},"How do I combine a column and a line chart in XlsxWriter?","\nCreate a column chart and a line chart, add their series, then call column_chart.combine(line_chart) and insert only the column chart.",[10,2410,2411,2414],{},[2334,2412,2413],{},"How do I put a series on a secondary axis in XlsxWriter?","\nAdd y2_axis set to True in the series options and configure the axis with set_y2_axis on the chart that owns the series.",[10,2416,2417,2420],{},[2334,2418,2419],{},"How do I create a chartsheet with XlsxWriter?","\nCall workbook.add_chartsheet(), then chartsheet.set_chart(chart) with a chart created by workbook.add_chart().",[10,2422,2423,2426],{},[2334,2424,2425],{},"How can I label the totals of a stacked column chart?","\nCombine a line chart of the totals on the same axis, hide its line and show markers with value data labels above each stack.",[29,2428,2430],{"id":2429},"related","Related",[2328,2432,2433,2439,2446,2453],{},[2331,2434,2435,2436,2438],{},"Up one level: ",[23,2437,26],{"href":25}," — reports with XlsxWriter.",[2331,2440,2441,2445],{},[23,2442,2444],{"href":2443},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-a-chart-to-an-excel-file-with-xlsxwriter\u002F","Add a Chart to an Excel File with xlsxwriter"," — chart basics.",[2331,2447,2448,2452],{},[23,2449,2451],{"href":2450},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002Fput-a-chart-on-its-own-chartsheet-with-openpyxl\u002F","Put a Chart on Its Own Chartsheet with openpyxl"," — the openpyxl way.",[2331,2454,2455,2459],{},[23,2456,2458],{"href":2457},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Flabel-chart-points-from-cell-values-with-xlsxwriter\u002F","Label Chart Points from Cell Values with xlsxwriter"," — custom data labels.",[2461,2462,2463],"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}html pre.shiki code .s_b0D, html code.shiki .s_b0D{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold}",{"title":39,"searchDepth":93,"depth":93,"links":2465},[2466,2467,2468,2469,2470,2471,2472,2473,2474],{"id":31,"depth":93,"text":32},{"id":66,"depth":93,"text":67},{"id":683,"depth":93,"text":684},{"id":1287,"depth":93,"text":1288},{"id":1937,"depth":93,"text":1938},{"id":2325,"depth":93,"text":2326},{"id":2378,"depth":93,"text":2379},{"id":2401,"depth":93,"text":2402},{"id":2429,"depth":93,"text":2430},"2026-10-02","Build combination charts and full-page chartsheets with XlsxWriter: columns and a line in one chart with the line on a secondary axis, a stacked column chart with a total line, charts fed from a pandas summary written to a data sheet, chartsheets that show one chart per tab, and checks of the generated chart XML so a broken chart is caught before anyone opens the file.","md",[2479,2481,2483,2485],{"q":2407,"a":2480},"Create a column chart and a line chart, add their series, then call column_chart.combine(line_chart) and insert only the column chart.",{"q":2413,"a":2482},"Add y2_axis set to True in the series options and configure the axis with set_y2_axis on the chart that owns the series.",{"q":2419,"a":2484},"Call workbook.add_chartsheet(), then chartsheet.set_chart(chart) with a chart created by workbook.add_chart().",{"q":2425,"a":2486},"Combine a line chart of the totals on the same axis, hide its line and show markers with value data labels above each stack.","combine chart types and chartsheets with xlsxwriter",null,{"breadcrumb":2490},[2491,2493,2496],{"name":2492,"item":350},"Home",{"name":2494,"item":2495},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":26,"item":25},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fcombine-chart-types-and-chartsheets-with-xlsxwriter",{"title":5,"description":2499},"XlsxWriter chart.combine() for column and line charts with a secondary y2 axis, stacked columns with a total line, data from pandas, add_chartsheet for full-page charts, and validating the chart XML.","combine-chart-types-and-chartsheets-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fcombine-chart-types-and-chartsheets-with-xlsxwriter\u002Findex",[2503,2504],"xlsxwriter","charts-and-images","how-to","O_-aAJwTP8xeD1ib9UmrBZUDEuUDvjMBH3vOe7mm6GM",[2508,2512],{"title":2509,"path":2510,"stem":2511,"children":-1},"Build a Waterfall Chart in Excel with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fbuild-a-waterfall-chart-in-excel-with-python","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fbuild-a-waterfall-chart-in-excel-with-python\u002Findex",{"title":2513,"path":2514,"stem":2515,"children":-1},"Define Names and Protect Sheets with XlsxWriter","\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fdefine-names-and-protect-sheets-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fdefine-names-and-protect-sheets-with-xlsxwriter\u002Findex",[2517,2519],{"path":2518,"title":26},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter",{"path":2520,"title":2494},"\u002Fformatting-and-charting-excel-reports-with-python",[],[2523,2527,2528,2531,2534,2537],{"path":2524,"title":2525,"kind":2526},"\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":2514,"title":2513,"kind":2505},{"path":2529,"title":2530,"kind":2505},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Ffreeze-panes-and-set-zoom-with-xlsxwriter","Freeze Panes and Set Zoom with XlsxWriter",{"path":2532,"title":2533,"kind":2505},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Finsert-checkboxes-with-xlsxwriter","Insert Checkboxes in Excel with xlsxwriter",{"path":2535,"title":2536,"kind":2505},"\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":2538,"title":2539,"kind":2505},"\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",1790972108522]