[{"data":1,"prerenderedAt":2198},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl":2190},{"id":4,"title":5,"body":6,"description":2182,"extension":2183,"meta":2184,"navigation":109,"path":2185,"seo":2186,"stem":2188,"__hash__":2189},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002Findex.md","Creating Charts in Excel with openpyxl",{"type":7,"value":8,"toc":2170},"minimark",[9,29,40,45,56,392,395,399,419,689,709,713,722,996,1003,1007,1010,1294,1301,1305,1308,1555,1559,1562,1607,1618,1927,1931,2034,2037,2041,2047,2053,2070,2091,2104,2108,2121,2125,2166],[10,11,12,13,17,18,22,23,28],"p",{},"A report that ships a table of numbers makes the reader do the work of spotting the trend. A chart does that work up front. With openpyxl you can write charts directly into the ",[14,15,16],"code",{},".xlsx"," file, and the result is a ",[19,20,21],"strong",{},"real Excel chart object"," — not a pasted image. Open the workbook in Excel or LibreOffice and you can click the chart, edit its data range, change its colors, and resize it like any chart you drew by hand. This cluster is the charting half of ",[24,25,27],"a",{"href":26},"\u002Fformatting-and-charting-excel-reports-with-python\u002F","Formatting and Charting Excel Reports with Python","; the formatting clusters handle how cells look, and these pages handle how the numbers are visualized.",[10,30,31,32,35,36,39],{},"Everything here builds on openpyxl's two core ideas: a chart object describes the chart, and ",[14,33,34],{},"Reference","\u002F",[14,37,38],{},"Series"," objects bind that chart to cell ranges on a worksheet. Get those two right and every chart type follows the same shape.",[41,42,44],"h2",{"id":43},"how-openpyxl-charts-actually-work","How openpyxl charts actually work",[10,46,47,48,50,51,55],{},"An openpyxl chart is a small declarative object stored inside the ",[14,49,16],{}," package. It does not contain the data — it contains ",[52,53,54],"em",{},"pointers"," to worksheet cells. When Excel opens the file, it reads those pointers, reads the live cell values, and renders the chart. That has one important consequence: change a number in the bound range and the chart updates, exactly as a manually drawn chart would.",[57,58,63],"pre",{"className":59,"code":60,"language":61,"meta":62,"style":62},"language-python shiki shiki-themes github-light github-dark","# pip install openpyxl\nfrom openpyxl import Workbook\nfrom openpyxl.chart import BarChart, Reference\n\nwb = Workbook()\nws = wb.active\nws.append([\"Quarter\", \"Revenue\"])\nfor row in [(\"Q1\", 120), (\"Q2\", 145), (\"Q3\", 138), (\"Q4\", 162)]:\n    ws.append(row)\n\nchart = BarChart()\ndata = Reference(ws, min_col=2, min_row=1, max_row=5)   # includes header\ncats = Reference(ws, min_col=1, min_row=2, max_row=5)    # excludes header\nchart.add_data(data, titles_from_data=True)\nchart.set_categories(cats)\nchart.title = \"Quarterly Revenue\"\n\nws.add_chart(chart, \"D2\")\nwb.save(\"chart_basics.xlsx\")\nprint(\"Saved chart_basics.xlsx — open it in Excel and click the chart\")\n","python","",[14,64,65,74,91,104,111,123,134,153,211,217,222,233,279,317,334,340,351,356,367,378],{"__ignoreMap":62},[66,67,70],"span",{"class":68,"line":69},"line",1,[66,71,73],{"class":72},"sJ8bj","# pip install openpyxl\n",[66,75,77,81,85,88],{"class":68,"line":76},2,[66,78,80],{"class":79},"szBVR","from",[66,82,84],{"class":83},"sVt8B"," openpyxl ",[66,86,87],{"class":79},"import",[66,89,90],{"class":83}," Workbook\n",[66,92,94,96,99,101],{"class":68,"line":93},3,[66,95,80],{"class":79},[66,97,98],{"class":83}," openpyxl.chart ",[66,100,87],{"class":79},[66,102,103],{"class":83}," BarChart, Reference\n",[66,105,107],{"class":68,"line":106},4,[66,108,110],{"emptyLinePlaceholder":109},true,"\n",[66,112,114,117,120],{"class":68,"line":113},5,[66,115,116],{"class":83},"wb ",[66,118,119],{"class":79},"=",[66,121,122],{"class":83}," Workbook()\n",[66,124,126,129,131],{"class":68,"line":125},6,[66,127,128],{"class":83},"ws ",[66,130,119],{"class":79},[66,132,133],{"class":83}," wb.active\n",[66,135,137,140,144,147,150],{"class":68,"line":136},7,[66,138,139],{"class":83},"ws.append([",[66,141,143],{"class":142},"sZZnC","\"Quarter\"",[66,145,146],{"class":83},", ",[66,148,149],{"class":142},"\"Revenue\"",[66,151,152],{"class":83},"])\n",[66,154,156,159,162,165,168,171,173,177,180,183,185,188,190,193,195,198,200,203,205,208],{"class":68,"line":155},8,[66,157,158],{"class":79},"for",[66,160,161],{"class":83}," row ",[66,163,164],{"class":79},"in",[66,166,167],{"class":83}," [(",[66,169,170],{"class":142},"\"Q1\"",[66,172,146],{"class":83},[66,174,176],{"class":175},"sj4cs","120",[66,178,179],{"class":83},"), (",[66,181,182],{"class":142},"\"Q2\"",[66,184,146],{"class":83},[66,186,187],{"class":175},"145",[66,189,179],{"class":83},[66,191,192],{"class":142},"\"Q3\"",[66,194,146],{"class":83},[66,196,197],{"class":175},"138",[66,199,179],{"class":83},[66,201,202],{"class":142},"\"Q4\"",[66,204,146],{"class":83},[66,206,207],{"class":175},"162",[66,209,210],{"class":83},")]:\n",[66,212,214],{"class":68,"line":213},9,[66,215,216],{"class":83},"    ws.append(row)\n",[66,218,220],{"class":68,"line":219},10,[66,221,110],{"emptyLinePlaceholder":109},[66,223,225,228,230],{"class":68,"line":224},11,[66,226,227],{"class":83},"chart ",[66,229,119],{"class":79},[66,231,232],{"class":83}," BarChart()\n",[66,234,236,239,241,244,248,250,253,255,258,260,263,265,268,270,273,276],{"class":68,"line":235},12,[66,237,238],{"class":83},"data ",[66,240,119],{"class":79},[66,242,243],{"class":83}," Reference(ws, ",[66,245,247],{"class":246},"s4XuR","min_col",[66,249,119],{"class":79},[66,251,252],{"class":175},"2",[66,254,146],{"class":83},[66,256,257],{"class":246},"min_row",[66,259,119],{"class":79},[66,261,262],{"class":175},"1",[66,264,146],{"class":83},[66,266,267],{"class":246},"max_row",[66,269,119],{"class":79},[66,271,272],{"class":175},"5",[66,274,275],{"class":83},")   ",[66,277,278],{"class":72},"# includes header\n",[66,280,282,285,287,289,291,293,295,297,299,301,303,305,307,309,311,314],{"class":68,"line":281},13,[66,283,284],{"class":83},"cats ",[66,286,119],{"class":79},[66,288,243],{"class":83},[66,290,247],{"class":246},[66,292,119],{"class":79},[66,294,262],{"class":175},[66,296,146],{"class":83},[66,298,257],{"class":246},[66,300,119],{"class":79},[66,302,252],{"class":175},[66,304,146],{"class":83},[66,306,267],{"class":246},[66,308,119],{"class":79},[66,310,272],{"class":175},[66,312,313],{"class":83},")    ",[66,315,316],{"class":72},"# excludes header\n",[66,318,320,323,326,328,331],{"class":68,"line":319},14,[66,321,322],{"class":83},"chart.add_data(data, ",[66,324,325],{"class":246},"titles_from_data",[66,327,119],{"class":79},[66,329,330],{"class":175},"True",[66,332,333],{"class":83},")\n",[66,335,337],{"class":68,"line":336},15,[66,338,339],{"class":83},"chart.set_categories(cats)\n",[66,341,343,346,348],{"class":68,"line":342},16,[66,344,345],{"class":83},"chart.title ",[66,347,119],{"class":79},[66,349,350],{"class":142}," \"Quarterly Revenue\"\n",[66,352,354],{"class":68,"line":353},17,[66,355,110],{"emptyLinePlaceholder":109},[66,357,359,362,365],{"class":68,"line":358},18,[66,360,361],{"class":83},"ws.add_chart(chart, ",[66,363,364],{"class":142},"\"D2\"",[66,366,333],{"class":83},[66,368,370,373,376],{"class":68,"line":369},19,[66,371,372],{"class":83},"wb.save(",[66,374,375],{"class":142},"\"chart_basics.xlsx\"",[66,377,333],{"class":83},[66,379,381,384,387,390],{"class":68,"line":380},20,[66,382,383],{"class":175},"print",[66,385,386],{"class":83},"(",[66,388,389],{"class":142},"\"Saved chart_basics.xlsx — open it in Excel and click the chart\"",[66,391,333],{"class":83},[10,393,394],{},"The chart is editable because it is described, not drawn. There is no pixel data to round-trip — Excel does the drawing.",[41,396,398],{"id":397},"binding-data-with-reference-and-series","Binding data with Reference and Series",[10,400,401,403,404,406,407,410,411,414,415,418],{},[14,402,34],{}," defines a rectangular block of cells. You pass it the worksheet plus the bounding rows and columns, and it becomes the data or the categories for a chart. The single most common mistake is mixing up which ",[14,405,34],{}," is the ",[19,408,409],{},"values"," and which is the ",[19,412,413],{},"categories",": values normally include the header row (so ",[14,416,417],{},"titles_from_data=True"," can read the series name), while categories never do.",[57,420,422],{"className":59,"code":421,"language":61,"meta":62,"style":62},"# pip install openpyxl\nfrom openpyxl import Workbook\nfrom openpyxl.chart import LineChart, Reference, Series\n\nwb = Workbook()\nws = wb.active\nws.append([\"Month\", \"Signups\", \"Churn\"])\nfor row in [(\"Jan\", 90, 12), (\"Feb\", 110, 15), (\"Mar\", 130, 11)]:\n    ws.append(row)\n\nchart = LineChart()\n# Two value columns -> two series. Header row supplies the series names.\ndata = Reference(ws, min_col=2, max_col=3, min_row=1, max_row=4)\nchart.add_data(data, titles_from_data=True)\ncats = Reference(ws, min_col=1, min_row=2, max_row=4)\nchart.set_categories(cats)\n\nprint(\"series count:\", len(chart.series))   # -> 2\nwb.save(\"two_series.xlsx\")\n",[14,423,424,428,438,449,453,461,469,488,543,547,551,560,565,608,620,652,656,660,680],{"__ignoreMap":62},[66,425,426],{"class":68,"line":69},[66,427,73],{"class":72},[66,429,430,432,434,436],{"class":68,"line":76},[66,431,80],{"class":79},[66,433,84],{"class":83},[66,435,87],{"class":79},[66,437,90],{"class":83},[66,439,440,442,444,446],{"class":68,"line":93},[66,441,80],{"class":79},[66,443,98],{"class":83},[66,445,87],{"class":79},[66,447,448],{"class":83}," LineChart, Reference, Series\n",[66,450,451],{"class":68,"line":106},[66,452,110],{"emptyLinePlaceholder":109},[66,454,455,457,459],{"class":68,"line":113},[66,456,116],{"class":83},[66,458,119],{"class":79},[66,460,122],{"class":83},[66,462,463,465,467],{"class":68,"line":125},[66,464,128],{"class":83},[66,466,119],{"class":79},[66,468,133],{"class":83},[66,470,471,473,476,478,481,483,486],{"class":68,"line":136},[66,472,139],{"class":83},[66,474,475],{"class":142},"\"Month\"",[66,477,146],{"class":83},[66,479,480],{"class":142},"\"Signups\"",[66,482,146],{"class":83},[66,484,485],{"class":142},"\"Churn\"",[66,487,152],{"class":83},[66,489,490,492,494,496,498,501,503,506,508,511,513,516,518,521,523,526,528,531,533,536,538,541],{"class":68,"line":155},[66,491,158],{"class":79},[66,493,161],{"class":83},[66,495,164],{"class":79},[66,497,167],{"class":83},[66,499,500],{"class":142},"\"Jan\"",[66,502,146],{"class":83},[66,504,505],{"class":175},"90",[66,507,146],{"class":83},[66,509,510],{"class":175},"12",[66,512,179],{"class":83},[66,514,515],{"class":142},"\"Feb\"",[66,517,146],{"class":83},[66,519,520],{"class":175},"110",[66,522,146],{"class":83},[66,524,525],{"class":175},"15",[66,527,179],{"class":83},[66,529,530],{"class":142},"\"Mar\"",[66,532,146],{"class":83},[66,534,535],{"class":175},"130",[66,537,146],{"class":83},[66,539,540],{"class":175},"11",[66,542,210],{"class":83},[66,544,545],{"class":68,"line":213},[66,546,216],{"class":83},[66,548,549],{"class":68,"line":219},[66,550,110],{"emptyLinePlaceholder":109},[66,552,553,555,557],{"class":68,"line":224},[66,554,227],{"class":83},[66,556,119],{"class":79},[66,558,559],{"class":83}," LineChart()\n",[66,561,562],{"class":68,"line":235},[66,563,564],{"class":72},"# Two value columns -> two series. Header row supplies the series names.\n",[66,566,567,569,571,573,575,577,579,581,584,586,589,591,593,595,597,599,601,603,606],{"class":68,"line":281},[66,568,238],{"class":83},[66,570,119],{"class":79},[66,572,243],{"class":83},[66,574,247],{"class":246},[66,576,119],{"class":79},[66,578,252],{"class":175},[66,580,146],{"class":83},[66,582,583],{"class":246},"max_col",[66,585,119],{"class":79},[66,587,588],{"class":175},"3",[66,590,146],{"class":83},[66,592,257],{"class":246},[66,594,119],{"class":79},[66,596,262],{"class":175},[66,598,146],{"class":83},[66,600,267],{"class":246},[66,602,119],{"class":79},[66,604,605],{"class":175},"4",[66,607,333],{"class":83},[66,609,610,612,614,616,618],{"class":68,"line":319},[66,611,322],{"class":83},[66,613,325],{"class":246},[66,615,119],{"class":79},[66,617,330],{"class":175},[66,619,333],{"class":83},[66,621,622,624,626,628,630,632,634,636,638,640,642,644,646,648,650],{"class":68,"line":336},[66,623,284],{"class":83},[66,625,119],{"class":79},[66,627,243],{"class":83},[66,629,247],{"class":246},[66,631,119],{"class":79},[66,633,262],{"class":175},[66,635,146],{"class":83},[66,637,257],{"class":246},[66,639,119],{"class":79},[66,641,252],{"class":175},[66,643,146],{"class":83},[66,645,267],{"class":246},[66,647,119],{"class":79},[66,649,605],{"class":175},[66,651,333],{"class":83},[66,653,654],{"class":68,"line":342},[66,655,339],{"class":83},[66,657,658],{"class":68,"line":353},[66,659,110],{"emptyLinePlaceholder":109},[66,661,662,664,666,669,671,674,677],{"class":68,"line":358},[66,663,383],{"class":175},[66,665,386],{"class":83},[66,667,668],{"class":142},"\"series count:\"",[66,670,146],{"class":83},[66,672,673],{"class":175},"len",[66,675,676],{"class":83},"(chart.series))   ",[66,678,679],{"class":72},"# -> 2\n",[66,681,682,684,687],{"class":68,"line":369},[66,683,372],{"class":83},[66,685,686],{"class":142},"\"two_series.xlsx\"",[66,688,333],{"class":83},[10,690,691,694,695,697,698,701,702,704,705,708],{},[14,692,693],{},"add_data"," builds one ",[14,696,38],{}," per column (or per row, with ",[14,699,700],{},"from_rows=True","). When you need fine control — a custom series title, or pulling columns that aren't adjacent — build a ",[14,703,38],{}," object yourself and append it to ",[14,706,707],{},"chart.series",".",[41,710,712],{"id":711},"a-bar-chart","A bar chart",[10,714,715,716,718,719,721],{},"Bar charts compare discrete categories. Build the chart, add a value ",[14,717,34],{}," with ",[14,720,417],{},", attach the category labels, then anchor it.",[57,723,725],{"className":59,"code":724,"language":61,"meta":62,"style":62},"# pip install openpyxl\nfrom openpyxl import Workbook\nfrom openpyxl.chart import BarChart, Reference\n\nwb = Workbook()\nws = wb.active\nws.append([\"Product\", \"Units\"])\nfor row in [(\"Widget\", 340), (\"Gadget\", 280), (\"Gizmo\", 410)]:\n    ws.append(row)\n\nchart = BarChart()\nchart.type = \"col\"          # vertical columns; \"bar\" gives horizontal\nchart.title = \"Units Sold by Product\"\nchart.x_axis.title = \"Product\"\nchart.y_axis.title = \"Units\"\n\ndata = Reference(ws, min_col=2, min_row=1, max_row=4)\nchart.add_data(data, titles_from_data=True)\nchart.set_categories(Reference(ws, min_col=1, min_row=2, max_row=4))\n\nws.add_chart(chart, \"D2\")\nwb.save(\"bar_chart.xlsx\")\nprint(\"Saved bar_chart.xlsx\")\n",[14,726,727,731,741,751,755,763,771,785,825,829,833,841,854,863,873,883,887,919,931,961,965,974,984],{"__ignoreMap":62},[66,728,729],{"class":68,"line":69},[66,730,73],{"class":72},[66,732,733,735,737,739],{"class":68,"line":76},[66,734,80],{"class":79},[66,736,84],{"class":83},[66,738,87],{"class":79},[66,740,90],{"class":83},[66,742,743,745,747,749],{"class":68,"line":93},[66,744,80],{"class":79},[66,746,98],{"class":83},[66,748,87],{"class":79},[66,750,103],{"class":83},[66,752,753],{"class":68,"line":106},[66,754,110],{"emptyLinePlaceholder":109},[66,756,757,759,761],{"class":68,"line":113},[66,758,116],{"class":83},[66,760,119],{"class":79},[66,762,122],{"class":83},[66,764,765,767,769],{"class":68,"line":125},[66,766,128],{"class":83},[66,768,119],{"class":79},[66,770,133],{"class":83},[66,772,773,775,778,780,783],{"class":68,"line":136},[66,774,139],{"class":83},[66,776,777],{"class":142},"\"Product\"",[66,779,146],{"class":83},[66,781,782],{"class":142},"\"Units\"",[66,784,152],{"class":83},[66,786,787,789,791,793,795,798,800,803,805,808,810,813,815,818,820,823],{"class":68,"line":155},[66,788,158],{"class":79},[66,790,161],{"class":83},[66,792,164],{"class":79},[66,794,167],{"class":83},[66,796,797],{"class":142},"\"Widget\"",[66,799,146],{"class":83},[66,801,802],{"class":175},"340",[66,804,179],{"class":83},[66,806,807],{"class":142},"\"Gadget\"",[66,809,146],{"class":83},[66,811,812],{"class":175},"280",[66,814,179],{"class":83},[66,816,817],{"class":142},"\"Gizmo\"",[66,819,146],{"class":83},[66,821,822],{"class":175},"410",[66,824,210],{"class":83},[66,826,827],{"class":68,"line":213},[66,828,216],{"class":83},[66,830,831],{"class":68,"line":219},[66,832,110],{"emptyLinePlaceholder":109},[66,834,835,837,839],{"class":68,"line":224},[66,836,227],{"class":83},[66,838,119],{"class":79},[66,840,232],{"class":83},[66,842,843,846,848,851],{"class":68,"line":235},[66,844,845],{"class":83},"chart.type ",[66,847,119],{"class":79},[66,849,850],{"class":142}," \"col\"",[66,852,853],{"class":72},"          # vertical columns; \"bar\" gives horizontal\n",[66,855,856,858,860],{"class":68,"line":281},[66,857,345],{"class":83},[66,859,119],{"class":79},[66,861,862],{"class":142}," \"Units Sold by Product\"\n",[66,864,865,868,870],{"class":68,"line":319},[66,866,867],{"class":83},"chart.x_axis.title ",[66,869,119],{"class":79},[66,871,872],{"class":142}," \"Product\"\n",[66,874,875,878,880],{"class":68,"line":336},[66,876,877],{"class":83},"chart.y_axis.title ",[66,879,119],{"class":79},[66,881,882],{"class":142}," \"Units\"\n",[66,884,885],{"class":68,"line":342},[66,886,110],{"emptyLinePlaceholder":109},[66,888,889,891,893,895,897,899,901,903,905,907,909,911,913,915,917],{"class":68,"line":353},[66,890,238],{"class":83},[66,892,119],{"class":79},[66,894,243],{"class":83},[66,896,247],{"class":246},[66,898,119],{"class":79},[66,900,252],{"class":175},[66,902,146],{"class":83},[66,904,257],{"class":246},[66,906,119],{"class":79},[66,908,262],{"class":175},[66,910,146],{"class":83},[66,912,267],{"class":246},[66,914,119],{"class":79},[66,916,605],{"class":175},[66,918,333],{"class":83},[66,920,921,923,925,927,929],{"class":68,"line":358},[66,922,322],{"class":83},[66,924,325],{"class":246},[66,926,119],{"class":79},[66,928,330],{"class":175},[66,930,333],{"class":83},[66,932,933,936,938,940,942,944,946,948,950,952,954,956,958],{"class":68,"line":369},[66,934,935],{"class":83},"chart.set_categories(Reference(ws, ",[66,937,247],{"class":246},[66,939,119],{"class":79},[66,941,262],{"class":175},[66,943,146],{"class":83},[66,945,257],{"class":246},[66,947,119],{"class":79},[66,949,252],{"class":175},[66,951,146],{"class":83},[66,953,267],{"class":246},[66,955,119],{"class":79},[66,957,605],{"class":175},[66,959,960],{"class":83},"))\n",[66,962,963],{"class":68,"line":380},[66,964,110],{"emptyLinePlaceholder":109},[66,966,968,970,972],{"class":68,"line":967},21,[66,969,361],{"class":83},[66,971,364],{"class":142},[66,973,333],{"class":83},[66,975,977,979,982],{"class":68,"line":976},22,[66,978,372],{"class":83},[66,980,981],{"class":142},"\"bar_chart.xlsx\"",[66,983,333],{"class":83},[66,985,987,989,991,994],{"class":68,"line":986},23,[66,988,383],{"class":175},[66,990,386],{"class":83},[66,992,993],{"class":142},"\"Saved bar_chart.xlsx\"",[66,995,333],{"class":83},[10,997,998,999,708],{},"The dedicated walkthrough — including the off-by-one row traps — is in ",[24,1000,1002],{"href":1001},"\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",[41,1004,1006],{"id":1005},"a-line-chart","A line chart",[10,1008,1009],{},"Line charts show a metric changing across an ordered axis, usually time. The mechanics match the bar chart; the difference is intent and the option to add markers.",[57,1011,1013],{"className":59,"code":1012,"language":61,"meta":62,"style":62},"# pip install openpyxl\nfrom openpyxl import Workbook\nfrom openpyxl.chart import LineChart, Reference\n\nwb = Workbook()\nws = wb.active\nws.append([\"Week\", \"Active Users\"])\nfor row in [(\"W1\", 1200), (\"W2\", 1340), (\"W3\", 1290), (\"W4\", 1510)]:\n    ws.append(row)\n\nchart = LineChart()\nchart.title = \"Weekly Active Users\"\nchart.y_axis.title = \"Users\"\nchart.x_axis.title = \"Week\"\n\ndata = Reference(ws, min_col=2, min_row=1, max_row=5)\nchart.add_data(data, titles_from_data=True)\nchart.set_categories(Reference(ws, min_col=1, min_row=2, max_row=5))\nchart.series[0].smooth = False   # straight segments between points\n\nws.add_chart(chart, \"D2\")\nwb.save(\"line_chart.xlsx\")\nprint(\"Saved line_chart.xlsx\")\n",[14,1014,1015,1019,1029,1040,1044,1052,1060,1074,1124,1128,1132,1140,1149,1158,1167,1171,1203,1215,1243,1262,1266,1274,1283],{"__ignoreMap":62},[66,1016,1017],{"class":68,"line":69},[66,1018,73],{"class":72},[66,1020,1021,1023,1025,1027],{"class":68,"line":76},[66,1022,80],{"class":79},[66,1024,84],{"class":83},[66,1026,87],{"class":79},[66,1028,90],{"class":83},[66,1030,1031,1033,1035,1037],{"class":68,"line":93},[66,1032,80],{"class":79},[66,1034,98],{"class":83},[66,1036,87],{"class":79},[66,1038,1039],{"class":83}," LineChart, Reference\n",[66,1041,1042],{"class":68,"line":106},[66,1043,110],{"emptyLinePlaceholder":109},[66,1045,1046,1048,1050],{"class":68,"line":113},[66,1047,116],{"class":83},[66,1049,119],{"class":79},[66,1051,122],{"class":83},[66,1053,1054,1056,1058],{"class":68,"line":125},[66,1055,128],{"class":83},[66,1057,119],{"class":79},[66,1059,133],{"class":83},[66,1061,1062,1064,1067,1069,1072],{"class":68,"line":136},[66,1063,139],{"class":83},[66,1065,1066],{"class":142},"\"Week\"",[66,1068,146],{"class":83},[66,1070,1071],{"class":142},"\"Active Users\"",[66,1073,152],{"class":83},[66,1075,1076,1078,1080,1082,1084,1087,1089,1092,1094,1097,1099,1102,1104,1107,1109,1112,1114,1117,1119,1122],{"class":68,"line":155},[66,1077,158],{"class":79},[66,1079,161],{"class":83},[66,1081,164],{"class":79},[66,1083,167],{"class":83},[66,1085,1086],{"class":142},"\"W1\"",[66,1088,146],{"class":83},[66,1090,1091],{"class":175},"1200",[66,1093,179],{"class":83},[66,1095,1096],{"class":142},"\"W2\"",[66,1098,146],{"class":83},[66,1100,1101],{"class":175},"1340",[66,1103,179],{"class":83},[66,1105,1106],{"class":142},"\"W3\"",[66,1108,146],{"class":83},[66,1110,1111],{"class":175},"1290",[66,1113,179],{"class":83},[66,1115,1116],{"class":142},"\"W4\"",[66,1118,146],{"class":83},[66,1120,1121],{"class":175},"1510",[66,1123,210],{"class":83},[66,1125,1126],{"class":68,"line":213},[66,1127,216],{"class":83},[66,1129,1130],{"class":68,"line":219},[66,1131,110],{"emptyLinePlaceholder":109},[66,1133,1134,1136,1138],{"class":68,"line":224},[66,1135,227],{"class":83},[66,1137,119],{"class":79},[66,1139,559],{"class":83},[66,1141,1142,1144,1146],{"class":68,"line":235},[66,1143,345],{"class":83},[66,1145,119],{"class":79},[66,1147,1148],{"class":142}," \"Weekly Active Users\"\n",[66,1150,1151,1153,1155],{"class":68,"line":281},[66,1152,877],{"class":83},[66,1154,119],{"class":79},[66,1156,1157],{"class":142}," \"Users\"\n",[66,1159,1160,1162,1164],{"class":68,"line":319},[66,1161,867],{"class":83},[66,1163,119],{"class":79},[66,1165,1166],{"class":142}," \"Week\"\n",[66,1168,1169],{"class":68,"line":336},[66,1170,110],{"emptyLinePlaceholder":109},[66,1172,1173,1175,1177,1179,1181,1183,1185,1187,1189,1191,1193,1195,1197,1199,1201],{"class":68,"line":342},[66,1174,238],{"class":83},[66,1176,119],{"class":79},[66,1178,243],{"class":83},[66,1180,247],{"class":246},[66,1182,119],{"class":79},[66,1184,252],{"class":175},[66,1186,146],{"class":83},[66,1188,257],{"class":246},[66,1190,119],{"class":79},[66,1192,262],{"class":175},[66,1194,146],{"class":83},[66,1196,267],{"class":246},[66,1198,119],{"class":79},[66,1200,272],{"class":175},[66,1202,333],{"class":83},[66,1204,1205,1207,1209,1211,1213],{"class":68,"line":353},[66,1206,322],{"class":83},[66,1208,325],{"class":246},[66,1210,119],{"class":79},[66,1212,330],{"class":175},[66,1214,333],{"class":83},[66,1216,1217,1219,1221,1223,1225,1227,1229,1231,1233,1235,1237,1239,1241],{"class":68,"line":358},[66,1218,935],{"class":83},[66,1220,247],{"class":246},[66,1222,119],{"class":79},[66,1224,262],{"class":175},[66,1226,146],{"class":83},[66,1228,257],{"class":246},[66,1230,119],{"class":79},[66,1232,252],{"class":175},[66,1234,146],{"class":83},[66,1236,267],{"class":246},[66,1238,119],{"class":79},[66,1240,272],{"class":175},[66,1242,960],{"class":83},[66,1244,1245,1248,1251,1254,1256,1259],{"class":68,"line":369},[66,1246,1247],{"class":83},"chart.series[",[66,1249,1250],{"class":175},"0",[66,1252,1253],{"class":83},"].smooth ",[66,1255,119],{"class":79},[66,1257,1258],{"class":175}," False",[66,1260,1261],{"class":72},"   # straight segments between points\n",[66,1263,1264],{"class":68,"line":380},[66,1265,110],{"emptyLinePlaceholder":109},[66,1267,1268,1270,1272],{"class":68,"line":967},[66,1269,361],{"class":83},[66,1271,364],{"class":142},[66,1273,333],{"class":83},[66,1275,1276,1278,1281],{"class":68,"line":976},[66,1277,372],{"class":83},[66,1279,1280],{"class":142},"\"line_chart.xlsx\"",[66,1282,333],{"class":83},[66,1284,1285,1287,1289,1292],{"class":68,"line":986},[66,1286,383],{"class":175},[66,1288,386],{"class":83},[66,1290,1291],{"class":142},"\"Saved line_chart.xlsx\"",[66,1293,333],{"class":83},[10,1295,1296,1297,708],{},"Time-series specifics — multiple series, markers, and date axes — are covered in ",[24,1298,1300],{"href":1299},"\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",[41,1302,1304],{"id":1303},"a-pie-chart","A pie chart",[10,1306,1307],{},"Pie charts show parts of a single whole, so they take exactly one data series and one set of category labels.",[57,1309,1311],{"className":59,"code":1310,"language":61,"meta":62,"style":62},"# pip install openpyxl\nfrom openpyxl import Workbook\nfrom openpyxl.chart import PieChart, Reference\n\nwb = Workbook()\nws = wb.active\nws.append([\"Channel\", \"Sessions\"])\nfor row in [(\"Organic\", 540), (\"Paid\", 230), (\"Referral\", 130), (\"Direct\", 100)]:\n    ws.append(row)\n\nchart = PieChart()\nchart.title = \"Traffic by Channel\"\n\ndata = Reference(ws, min_col=2, min_row=1, max_row=5)\nchart.add_data(data, titles_from_data=True)\nchart.set_categories(Reference(ws, min_col=1, min_row=2, max_row=5))\n\nws.add_chart(chart, \"D2\")\nwb.save(\"pie_chart.xlsx\")\nprint(\"Saved pie_chart.xlsx\")\n",[14,1312,1313,1317,1327,1338,1342,1350,1358,1372,1421,1425,1429,1438,1447,1451,1483,1495,1523,1527,1535,1544],{"__ignoreMap":62},[66,1314,1315],{"class":68,"line":69},[66,1316,73],{"class":72},[66,1318,1319,1321,1323,1325],{"class":68,"line":76},[66,1320,80],{"class":79},[66,1322,84],{"class":83},[66,1324,87],{"class":79},[66,1326,90],{"class":83},[66,1328,1329,1331,1333,1335],{"class":68,"line":93},[66,1330,80],{"class":79},[66,1332,98],{"class":83},[66,1334,87],{"class":79},[66,1336,1337],{"class":83}," PieChart, Reference\n",[66,1339,1340],{"class":68,"line":106},[66,1341,110],{"emptyLinePlaceholder":109},[66,1343,1344,1346,1348],{"class":68,"line":113},[66,1345,116],{"class":83},[66,1347,119],{"class":79},[66,1349,122],{"class":83},[66,1351,1352,1354,1356],{"class":68,"line":125},[66,1353,128],{"class":83},[66,1355,119],{"class":79},[66,1357,133],{"class":83},[66,1359,1360,1362,1365,1367,1370],{"class":68,"line":136},[66,1361,139],{"class":83},[66,1363,1364],{"class":142},"\"Channel\"",[66,1366,146],{"class":83},[66,1368,1369],{"class":142},"\"Sessions\"",[66,1371,152],{"class":83},[66,1373,1374,1376,1378,1380,1382,1385,1387,1390,1392,1395,1397,1400,1402,1405,1407,1409,1411,1414,1416,1419],{"class":68,"line":155},[66,1375,158],{"class":79},[66,1377,161],{"class":83},[66,1379,164],{"class":79},[66,1381,167],{"class":83},[66,1383,1384],{"class":142},"\"Organic\"",[66,1386,146],{"class":83},[66,1388,1389],{"class":175},"540",[66,1391,179],{"class":83},[66,1393,1394],{"class":142},"\"Paid\"",[66,1396,146],{"class":83},[66,1398,1399],{"class":175},"230",[66,1401,179],{"class":83},[66,1403,1404],{"class":142},"\"Referral\"",[66,1406,146],{"class":83},[66,1408,535],{"class":175},[66,1410,179],{"class":83},[66,1412,1413],{"class":142},"\"Direct\"",[66,1415,146],{"class":83},[66,1417,1418],{"class":175},"100",[66,1420,210],{"class":83},[66,1422,1423],{"class":68,"line":213},[66,1424,216],{"class":83},[66,1426,1427],{"class":68,"line":219},[66,1428,110],{"emptyLinePlaceholder":109},[66,1430,1431,1433,1435],{"class":68,"line":224},[66,1432,227],{"class":83},[66,1434,119],{"class":79},[66,1436,1437],{"class":83}," PieChart()\n",[66,1439,1440,1442,1444],{"class":68,"line":235},[66,1441,345],{"class":83},[66,1443,119],{"class":79},[66,1445,1446],{"class":142}," \"Traffic by Channel\"\n",[66,1448,1449],{"class":68,"line":281},[66,1450,110],{"emptyLinePlaceholder":109},[66,1452,1453,1455,1457,1459,1461,1463,1465,1467,1469,1471,1473,1475,1477,1479,1481],{"class":68,"line":319},[66,1454,238],{"class":83},[66,1456,119],{"class":79},[66,1458,243],{"class":83},[66,1460,247],{"class":246},[66,1462,119],{"class":79},[66,1464,252],{"class":175},[66,1466,146],{"class":83},[66,1468,257],{"class":246},[66,1470,119],{"class":79},[66,1472,262],{"class":175},[66,1474,146],{"class":83},[66,1476,267],{"class":246},[66,1478,119],{"class":79},[66,1480,272],{"class":175},[66,1482,333],{"class":83},[66,1484,1485,1487,1489,1491,1493],{"class":68,"line":336},[66,1486,322],{"class":83},[66,1488,325],{"class":246},[66,1490,119],{"class":79},[66,1492,330],{"class":175},[66,1494,333],{"class":83},[66,1496,1497,1499,1501,1503,1505,1507,1509,1511,1513,1515,1517,1519,1521],{"class":68,"line":342},[66,1498,935],{"class":83},[66,1500,247],{"class":246},[66,1502,119],{"class":79},[66,1504,262],{"class":175},[66,1506,146],{"class":83},[66,1508,257],{"class":246},[66,1510,119],{"class":79},[66,1512,252],{"class":175},[66,1514,146],{"class":83},[66,1516,267],{"class":246},[66,1518,119],{"class":79},[66,1520,272],{"class":175},[66,1522,960],{"class":83},[66,1524,1525],{"class":68,"line":353},[66,1526,110],{"emptyLinePlaceholder":109},[66,1528,1529,1531,1533],{"class":68,"line":358},[66,1530,361],{"class":83},[66,1532,364],{"class":142},[66,1534,333],{"class":83},[66,1536,1537,1539,1542],{"class":68,"line":369},[66,1538,372],{"class":83},[66,1540,1541],{"class":142},"\"pie_chart.xlsx\"",[66,1543,333],{"class":83},[66,1545,1546,1548,1550,1553],{"class":68,"line":380},[66,1547,383],{"class":175},[66,1549,386],{"class":83},[66,1551,1552],{"class":142},"\"Saved pie_chart.xlsx\"",[66,1554,333],{"class":83},[41,1556,1558],{"id":1557},"titles-axis-labels-legend-and-position","Titles, axis labels, legend, and position",[10,1560,1561],{},"A few properties cover almost every labeling need, and they are the same across chart types:",[1563,1564,1565,1572,1582,1592,1598],"ul",{},[1566,1567,1568,1571],"li",{},[14,1569,1570],{},"chart.title"," — the chart heading.",[1566,1573,1574,1577,1578,1581],{},[14,1575,1576],{},"chart.x_axis.title"," \u002F ",[14,1579,1580],{},"chart.y_axis.title"," — axis captions (ignored by pie charts).",[1566,1583,1584,1587,1588,1591],{},[14,1585,1586],{},"chart.legend"," — set ",[14,1589,1590],{},"chart.legend = None"," to drop the legend; it shows automatically when there is more than one series.",[1566,1593,1594,1597],{},[14,1595,1596],{},"chart.style"," — an integer 1–48 selecting a built-in Excel color\u002Fstyle preset.",[1566,1599,1600,1577,1603,1606],{},[14,1601,1602],{},"chart.height",[14,1604,1605],{},"chart.width"," — size in centimeters.",[10,1608,1609,1610,1613,1614,1617],{},"Position is set when you anchor the chart: ",[14,1611,1612],{},"ws.add_chart(chart, \"E2\")"," places the chart's ",[19,1615,1616],{},"top-left corner"," at cell E2. The cell is an anchor only — the chart floats above the grid and does not resize with the column.",[57,1619,1621],{"className":59,"code":1620,"language":61,"meta":62,"style":62},"# pip install openpyxl\nfrom openpyxl import Workbook\nfrom openpyxl.chart import BarChart, Reference\n\nwb = Workbook()\nws = wb.active\nws.append([\"Region\", \"Sales\"])\nfor row in [(\"North\", 220), (\"South\", 310), (\"East\", 190), (\"West\", 275)]:\n    ws.append(row)\n\nchart = BarChart()\nchart.title = \"Sales by Region\"\nchart.x_axis.title = \"Region\"\nchart.y_axis.title = \"Sales ($000s)\"\nchart.style = 10\nchart.height = 7      # cm\nchart.width = 14      # cm\nchart.legend = None   # single series — legend adds nothing\n\nchart.add_data(Reference(ws, min_col=2, min_row=1, max_row=5), titles_from_data=True)\nchart.set_categories(Reference(ws, min_col=1, min_row=2, max_row=5))\n\nws.add_chart(chart, \"E2\")\nwb.save(\"labeled_chart.xlsx\")\nprint(\"Saved labeled_chart.xlsx at anchor E2\")\n",[14,1622,1623,1627,1637,1647,1651,1659,1667,1681,1731,1735,1739,1747,1756,1765,1774,1784,1797,1809,1822,1826,1864,1892,1896,1905,1915],{"__ignoreMap":62},[66,1624,1625],{"class":68,"line":69},[66,1626,73],{"class":72},[66,1628,1629,1631,1633,1635],{"class":68,"line":76},[66,1630,80],{"class":79},[66,1632,84],{"class":83},[66,1634,87],{"class":79},[66,1636,90],{"class":83},[66,1638,1639,1641,1643,1645],{"class":68,"line":93},[66,1640,80],{"class":79},[66,1642,98],{"class":83},[66,1644,87],{"class":79},[66,1646,103],{"class":83},[66,1648,1649],{"class":68,"line":106},[66,1650,110],{"emptyLinePlaceholder":109},[66,1652,1653,1655,1657],{"class":68,"line":113},[66,1654,116],{"class":83},[66,1656,119],{"class":79},[66,1658,122],{"class":83},[66,1660,1661,1663,1665],{"class":68,"line":125},[66,1662,128],{"class":83},[66,1664,119],{"class":79},[66,1666,133],{"class":83},[66,1668,1669,1671,1674,1676,1679],{"class":68,"line":136},[66,1670,139],{"class":83},[66,1672,1673],{"class":142},"\"Region\"",[66,1675,146],{"class":83},[66,1677,1678],{"class":142},"\"Sales\"",[66,1680,152],{"class":83},[66,1682,1683,1685,1687,1689,1691,1694,1696,1699,1701,1704,1706,1709,1711,1714,1716,1719,1721,1724,1726,1729],{"class":68,"line":155},[66,1684,158],{"class":79},[66,1686,161],{"class":83},[66,1688,164],{"class":79},[66,1690,167],{"class":83},[66,1692,1693],{"class":142},"\"North\"",[66,1695,146],{"class":83},[66,1697,1698],{"class":175},"220",[66,1700,179],{"class":83},[66,1702,1703],{"class":142},"\"South\"",[66,1705,146],{"class":83},[66,1707,1708],{"class":175},"310",[66,1710,179],{"class":83},[66,1712,1713],{"class":142},"\"East\"",[66,1715,146],{"class":83},[66,1717,1718],{"class":175},"190",[66,1720,179],{"class":83},[66,1722,1723],{"class":142},"\"West\"",[66,1725,146],{"class":83},[66,1727,1728],{"class":175},"275",[66,1730,210],{"class":83},[66,1732,1733],{"class":68,"line":213},[66,1734,216],{"class":83},[66,1736,1737],{"class":68,"line":219},[66,1738,110],{"emptyLinePlaceholder":109},[66,1740,1741,1743,1745],{"class":68,"line":224},[66,1742,227],{"class":83},[66,1744,119],{"class":79},[66,1746,232],{"class":83},[66,1748,1749,1751,1753],{"class":68,"line":235},[66,1750,345],{"class":83},[66,1752,119],{"class":79},[66,1754,1755],{"class":142}," \"Sales by Region\"\n",[66,1757,1758,1760,1762],{"class":68,"line":281},[66,1759,867],{"class":83},[66,1761,119],{"class":79},[66,1763,1764],{"class":142}," \"Region\"\n",[66,1766,1767,1769,1771],{"class":68,"line":319},[66,1768,877],{"class":83},[66,1770,119],{"class":79},[66,1772,1773],{"class":142}," \"Sales ($000s)\"\n",[66,1775,1776,1779,1781],{"class":68,"line":336},[66,1777,1778],{"class":83},"chart.style ",[66,1780,119],{"class":79},[66,1782,1783],{"class":175}," 10\n",[66,1785,1786,1789,1791,1794],{"class":68,"line":342},[66,1787,1788],{"class":83},"chart.height ",[66,1790,119],{"class":79},[66,1792,1793],{"class":175}," 7",[66,1795,1796],{"class":72},"      # cm\n",[66,1798,1799,1802,1804,1807],{"class":68,"line":353},[66,1800,1801],{"class":83},"chart.width ",[66,1803,119],{"class":79},[66,1805,1806],{"class":175}," 14",[66,1808,1796],{"class":72},[66,1810,1811,1814,1816,1819],{"class":68,"line":358},[66,1812,1813],{"class":83},"chart.legend ",[66,1815,119],{"class":79},[66,1817,1818],{"class":175}," None",[66,1820,1821],{"class":72},"   # single series — legend adds nothing\n",[66,1823,1824],{"class":68,"line":369},[66,1825,110],{"emptyLinePlaceholder":109},[66,1827,1828,1831,1833,1835,1837,1839,1841,1843,1845,1847,1849,1851,1853,1856,1858,1860,1862],{"class":68,"line":380},[66,1829,1830],{"class":83},"chart.add_data(Reference(ws, ",[66,1832,247],{"class":246},[66,1834,119],{"class":79},[66,1836,252],{"class":175},[66,1838,146],{"class":83},[66,1840,257],{"class":246},[66,1842,119],{"class":79},[66,1844,262],{"class":175},[66,1846,146],{"class":83},[66,1848,267],{"class":246},[66,1850,119],{"class":79},[66,1852,272],{"class":175},[66,1854,1855],{"class":83},"), ",[66,1857,325],{"class":246},[66,1859,119],{"class":79},[66,1861,330],{"class":175},[66,1863,333],{"class":83},[66,1865,1866,1868,1870,1872,1874,1876,1878,1880,1882,1884,1886,1888,1890],{"class":68,"line":967},[66,1867,935],{"class":83},[66,1869,247],{"class":246},[66,1871,119],{"class":79},[66,1873,262],{"class":175},[66,1875,146],{"class":83},[66,1877,257],{"class":246},[66,1879,119],{"class":79},[66,1881,252],{"class":175},[66,1883,146],{"class":83},[66,1885,267],{"class":246},[66,1887,119],{"class":79},[66,1889,272],{"class":175},[66,1891,960],{"class":83},[66,1893,1894],{"class":68,"line":976},[66,1895,110],{"emptyLinePlaceholder":109},[66,1897,1898,1900,1903],{"class":68,"line":986},[66,1899,361],{"class":83},[66,1901,1902],{"class":142},"\"E2\"",[66,1904,333],{"class":83},[66,1906,1908,1910,1913],{"class":68,"line":1907},24,[66,1909,372],{"class":83},[66,1911,1912],{"class":142},"\"labeled_chart.xlsx\"",[66,1914,333],{"class":83},[66,1916,1918,1920,1922,1925],{"class":68,"line":1917},25,[66,1919,383],{"class":175},[66,1921,386],{"class":83},[66,1923,1924],{"class":142},"\"Saved labeled_chart.xlsx at anchor E2\"",[66,1926,333],{"class":83},[41,1928,1930],{"id":1929},"choosing-a-chart-type","Choosing a chart type",[1932,1933,1934,1953],"table",{},[1935,1936,1937],"thead",{},[1938,1939,1940,1944,1947,1950],"tr",{},[1941,1942,1943],"th",{},"Chart type",[1941,1945,1946],{},"openpyxl class",[1941,1948,1949],{},"Use when",[1941,1951,1952],{},"Series supported",[1954,1955,1956,1973,1988,2004,2019],"tbody",{},[1938,1957,1958,1962,1967,1970],{},[1959,1960,1961],"td",{},"Column \u002F bar",[1959,1963,1964],{},[14,1965,1966],{},"BarChart",[1959,1968,1969],{},"Comparing values across discrete categories",[1959,1971,1972],{},"One or many",[1938,1974,1975,1978,1983,1986],{},[1959,1976,1977],{},"Line",[1959,1979,1980],{},[14,1981,1982],{},"LineChart",[1959,1984,1985],{},"A metric trending over an ordered axis (usually time)",[1959,1987,1972],{},[1938,1989,1990,1993,1998,2001],{},[1959,1991,1992],{},"Pie",[1959,1994,1995],{},[14,1996,1997],{},"PieChart",[1959,1999,2000],{},"Parts of a single 100% whole",[1959,2002,2003],{},"Exactly one",[1938,2005,2006,2009,2014,2017],{},[1959,2007,2008],{},"Scatter",[1959,2010,2011],{},[14,2012,2013],{},"ScatterChart",[1959,2015,2016],{},"Relationship between two numeric variables",[1959,2018,1972],{},[1938,2020,2021,2024,2029,2032],{},[1959,2022,2023],{},"Area",[1959,2025,2026],{},[14,2027,2028],{},"AreaChart",[1959,2030,2031],{},"Cumulative magnitude over time, stacked totals",[1959,2033,1972],{},[10,2035,2036],{},"When in doubt: compare → bar, trend → line, composition → pie (and only for a handful of slices).",[41,2038,2040],{"id":2039},"frequently-asked-questions","Frequently asked questions",[10,2042,2043,2046],{},[19,2044,2045],{},"Are openpyxl charts images or real charts?"," Real Excel charts. They are stored as chart definitions that point at worksheet cells, so they stay fully editable in Excel and update when the underlying cells change.",[10,2048,2049,2052],{},[19,2050,2051],{},"Can openpyxl render a chart to a PNG?"," No. openpyxl writes the chart definition but does not draw it — only a spreadsheet application (Excel or LibreOffice) renders it. To export an image you must open the file in one of those applications, for example by automating LibreOffice headless conversion.",[10,2054,2055,2058,2059,2061,2062,2064,2065,35,2067,2069],{},[19,2056,2057],{},"Why is my chart empty or missing a series?"," Almost always a ",[14,2060,34],{}," bounds problem: the value range didn't include the rows you expected, or the header row was left out so ",[14,2063,325],{}," had nothing to read. Double-check ",[14,2066,257],{},[14,2068,267],{}," against the data.",[10,2071,2072,2075,2076,2079,2080,2082,2083,2085,2086,2079,2089,708],{},[19,2073,2074],{},"Do I include the header row in the Reference?"," Include it in the ",[19,2077,2078],{},"value"," ",[14,2081,34],{}," when you use ",[14,2084,417],{},", so the series name is read from the header. Never include it in the ",[19,2087,2088],{},"category",[14,2090,34],{},[10,2092,2093,2096,2097,146,2100,2103],{},[19,2094,2095],{},"Can I put several charts on one sheet?"," Yes. Build each chart and anchor it at a different cell — ",[14,2098,2099],{},"ws.add_chart(c1, \"E2\")",[14,2101,2102],{},"ws.add_chart(c2, \"E20\")",". Multiple charts coexist on a sheet without conflict.",[41,2105,2107],{"id":2106},"conclusion","Conclusion",[10,2109,2110,2111,2113,2114,2116,2117,2120],{},"openpyxl charts are native Excel objects bound to cell ranges through ",[14,2112,34],{}," and ",[14,2115,38],{},". Once you understand that the value range usually carries the header (for the series name) and the category range never does, every chart type — bar, line, pie, scatter, area — is the same three steps: build the chart, add data, set categories, then anchor it with ",[14,2118,2119],{},"ws.add_chart",". The one limitation to remember is rendering: openpyxl defines the chart but relies on Excel or LibreOffice to draw it.",[41,2122,2124],{"id":2123},"where-to-go-next","Where to go next",[1563,2126,2127,2132,2139,2155],{},[1566,2128,2129,2130],{},"Up to the pillar: ",[24,2131,27],{"href":26},[1566,2133,2134,2135,2113,2137],{},"This cluster's guides: ",[24,2136,1002],{"href":1001},[24,2138,1300],{"href":1299},[1566,2140,2141,2142,146,2146,2150,2151],{},"Sibling clusters: ",[24,2143,2145],{"href":2144},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002F","Styling Excel Cells with openpyxl",[24,2147,2149],{"href":2148},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002F","Applying Number and Date Formats in Excel",", and ",[24,2152,2154],{"href":2153},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002F","Inserting Images and Logos into Excel",[1566,2156,2157,2158,2113,2162],{},"Related: ",[24,2159,2161],{"href":2160},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002F","Using openpyxl for Excel File Manipulation",[24,2163,2165],{"href":2164},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002F","Building Multi-Sheet Excel Dashboards",[2167,2168,2169],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}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);}",{"title":62,"searchDepth":76,"depth":76,"links":2171},[2172,2173,2174,2175,2176,2177,2178,2179,2180,2181],{"id":43,"depth":76,"text":44},{"id":397,"depth":76,"text":398},{"id":711,"depth":76,"text":712},{"id":1005,"depth":76,"text":1006},{"id":1303,"depth":76,"text":1304},{"id":1557,"depth":76,"text":1558},{"id":1929,"depth":76,"text":1930},{"id":2039,"depth":76,"text":2040},{"id":2106,"depth":76,"text":2107},{"id":2123,"depth":76,"text":2124},"Build native, editable Excel charts from Python with openpyxl: bind data with Reference and Series, make bar, line, and pie charts, add titles and legends, and anchor them.","md",{},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl",{"title":5,"description":2187},"Generate real Excel charts from Python using openpyxl. Bind worksheet ranges with Reference and Series, build bar, line, and pie charts, label axes, and position them.","formatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002Findex","3CkzVox_USIxxj9D1l9gKk1Djxk3X30_woORuYz9nnI",[2191,2195],{"title":2192,"path":2193,"stem":2194,"children":-1},"Format Excel Cells as Currency with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-excel-cells-as-currency-with-python","formatting-and-charting-excel-reports-with-python\u002Fapplying-number-and-date-formats-in-excel\u002Fformat-excel-cells-as-currency-with-python\u002Findex",{"title":1300,"path":2196,"stem":2197,"children":-1},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002Fadd-line-chart-to-excel-report-with-python","formatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002Fadd-line-chart-to-excel-report-with-python\u002Findex",1781773160681]