[{"data":1,"prerenderedAt":1941},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fplot-charts-with-matplotlib-in-python-in-excel":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fplot-charts-with-matplotlib-in-python-in-excel":1910,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fplot-charts-with-matplotlib-in-python-in-excel":1918,"children:\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fplot-charts-with-matplotlib-in-python-in-excel":1923,"related:\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fplot-charts-with-matplotlib-in-python-in-excel":1924},{"id":4,"title":5,"body":6,"dateModified":1876,"datePublished":1876,"description":1877,"extension":1878,"faq":1879,"keyword":1888,"kind":1889,"meta":1890,"navigation":278,"path":1899,"seo":1900,"slug":1903,"stem":1904,"topics":1905,"type":1908,"__hash__":1909},"docs\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fplot-charts-with-matplotlib-in-python-in-excel\u002Findex.md","Plot Charts with matplotlib in Python in Excel",{"type":7,"value":8,"toc":1862},"minimark",[9,32,154,159,194,198,201,395,406,410,417,443,515,518,522,528,788,807,811,818,1083,1097,1207,1211,1214,1328,1339,1343,1346,1630,1650,1664,1668,1772,1776,1783,1787,1790,1794,1800,1806,1812,1818,1822,1858],[10,11,12,13,17,18,21,22,25,26,31],"p",{},"Excel's chart gallery covers the everyday cases well and runs out quickly after that: no small multiples,\nno regression bands, no distribution plots, and a lot of clicking to reproduce the same chart for twelve\nregions. Python in Excel brings matplotlib and seaborn into the workbook — both are imported by default as\n",[14,15,16],"code",{},"plt"," and ",[14,19,20],{},"sns"," — so a ",[14,23,24],{},"=PY"," cell can draw any chart those libraries can. The result arrives as an\nimage, which changes how you size, place and refresh it. This guide from\n",[27,28,30],"a",{"href":29},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002F","Using Python in Excel"," covers the\nwhole path from table to finished chart.",[33,34,42,43,42,47,42,51,42,58,42,67,42,74,42,79,42,86,42,91,42,95,42,100,42,104,42,108,42,111,42,114,42,118,42,121,42,125,42,129,42,132,42,137,42,142,42,145,42,148],"svg",{"viewBox":35,"role":36,"ariaLabelledBy":37,"xmlns":40,"style":41},"0 0 760 156","img",[38,39],"plt-path-t","plt-path-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:760px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[44,45,46],"title",{"id":38},"How a Python chart gets from a table to the sheet",[48,49,50],"desc",{"id":39},"The formula reads a table with xl, draws a matplotlib figure, and returns it as an image object. The image is then either shown floating over the grid or converted to an Excel value that sits inside the cell.",[52,53],"rect",{"x":54,"y":54,"width":55,"height":56,"fill":57},"0","760","156","#ffffff",[52,59],{"x":60,"y":60,"width":61,"height":62,"rx":63,"fill":64,"stroke":65,"style":66},"20","150","86","12","#e7ebef","var(--line,#cdd5e6)","stroke-width:2px",[68,69,73],"text",{"x":70,"y":71,"style":72},"95","50","font-size:14px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","xl(table)",[68,75,78],{"x":70,"y":76,"style":77},"72","font-size:11.5px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle","DataFrame in",[80,81],"line",{"x1":82,"y1":83,"x2":84,"y2":83,"stroke":85,"style":66},"175","63","204","var(--brand,#5b5cf0)",[87,88],"polygon",{"points":89,"fill":90},"207,63 198,58 198,68","#5b5cf0",[52,92],{"x":93,"y":60,"width":61,"height":62,"rx":63,"fill":94,"stroke":85,"style":66},"210","#f0f4ff",[68,96,99],{"x":97,"y":71,"style":98},"285","font-size:14px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","matplotlib",[68,101,103],{"x":97,"y":76,"style":102},"font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","draw the figure",[80,105],{"x1":106,"y1":83,"x2":107,"y2":83,"stroke":85,"style":66},"365","394",[87,109],{"points":110,"fill":90},"397,63 388,58 388,68",[52,112],{"x":113,"y":60,"width":61,"height":62,"rx":63,"fill":94,"stroke":85,"style":66},"400",[68,115,117],{"x":116,"y":71,"style":98},"475","image object",[68,119,120],{"x":116,"y":76,"style":102},"returned to",[68,122,124],{"x":116,"y":123,"style":102},"92","the cell",[80,126],{"x1":127,"y1":83,"x2":128,"y2":83,"stroke":85,"style":66},"555","584",[87,130],{"points":131,"fill":90},"587,63 578,58 578,68",[52,133],{"x":134,"y":60,"width":61,"height":62,"rx":63,"fill":135,"stroke":136,"style":66},"590","#d9f4f1","var(--teal,#0f9488)",[68,138,141],{"x":139,"y":71,"style":140},"665","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","show it",[68,143,144],{"x":139,"y":76,"style":102},"over cells, or",[68,146,147],{"x":139,"y":123,"style":102},"in the cell",[68,149,153],{"x":150,"y":151,"style":152},"380","140","font-size:12.5px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle","the chart is a picture, redrawn in the cloud on every recalculation",[155,156,158],"h2",{"id":157},"prerequisites","Prerequisites",[160,161,162,166,187],"ul",{},[163,164,165],"li",{},"Excel with Python in Excel available and enabled.",[163,167,168,169,172,173,176,177,176,180,17,183,186],{},"A table named ",[14,170,171],{},"Sales"," with ",[14,174,175],{},"Date",", ",[14,178,179],{},"Region",[14,181,182],{},"Rep",[14,184,185],{},"Amount"," columns.",[163,188,189,190,193],{},"Familiarity with matplotlib's figure-and-axes interface helps; everything here uses it explicitly rather than\nthe implicit ",[14,191,192],{},"plt.plot"," state machine, which makes the figure that is returned unambiguous.",[155,195,197],{"id":196},"step-1-draw-a-first-chart-and-return-the-figure","Step 1 — Draw a first chart and return the figure",[10,199,200],{},"Create a figure and axes, plot on the axes, and make the figure the last expression of the formula. A monthly\nrevenue line is a good first chart because it needs a resample, which Excel's own charts cannot do.",[202,203,208],"pre",{"className":204,"code":205,"language":206,"meta":207,"style":207},"language-python shiki shiki-themes github-light github-dark-high-contrast","sales = xl(\"Sales[#All]\", headers=True)\nmonthly = sales.set_index(\"Date\")[\"Amount\"].resample(\"MS\").sum()\n\nfig, ax = plt.subplots(figsize=(6, 3.2))\nax.plot(monthly.index, monthly.values, marker=\"o\", linewidth=2)\nax.set_title(\"Revenue by month\")\nax.set_ylabel(\"Amount\")\nax.grid(axis=\"y\", alpha=0.3)\nfig.tight_layout()\nfig\n","python","",[14,209,210,244,273,280,310,336,347,357,383,389],{"__ignoreMap":207},[211,212,214,218,222,225,229,231,235,237,241],"span",{"class":80,"line":213},1,[211,215,217],{"class":216},"skGVy","sales ",[211,219,221],{"class":220},"s-kum","=",[211,223,224],{"class":216}," xl(",[211,226,228],{"class":227},"srMev","\"Sales[#All]\"",[211,230,176],{"class":216},[211,232,234],{"class":233},"sa561","headers",[211,236,221],{"class":220},[211,238,240],{"class":239},"sP0c6","True",[211,242,243],{"class":216},")\n",[211,245,247,250,252,255,258,261,264,267,270],{"class":80,"line":246},2,[211,248,249],{"class":216},"monthly ",[211,251,221],{"class":220},[211,253,254],{"class":216}," sales.set_index(",[211,256,257],{"class":227},"\"Date\"",[211,259,260],{"class":216},")[",[211,262,263],{"class":227},"\"Amount\"",[211,265,266],{"class":216},"].resample(",[211,268,269],{"class":227},"\"MS\"",[211,271,272],{"class":216},").sum()\n",[211,274,276],{"class":80,"line":275},3,[211,277,279],{"emptyLinePlaceholder":278},true,"\n",[211,281,283,286,288,291,294,296,299,302,304,307],{"class":80,"line":282},4,[211,284,285],{"class":216},"fig, ax ",[211,287,221],{"class":220},[211,289,290],{"class":216}," plt.subplots(",[211,292,293],{"class":233},"figsize",[211,295,221],{"class":220},[211,297,298],{"class":216},"(",[211,300,301],{"class":239},"6",[211,303,176],{"class":216},[211,305,306],{"class":239},"3.2",[211,308,309],{"class":216},"))\n",[211,311,313,316,319,321,324,326,329,331,334],{"class":80,"line":312},5,[211,314,315],{"class":216},"ax.plot(monthly.index, monthly.values, ",[211,317,318],{"class":233},"marker",[211,320,221],{"class":220},[211,322,323],{"class":227},"\"o\"",[211,325,176],{"class":216},[211,327,328],{"class":233},"linewidth",[211,330,221],{"class":220},[211,332,333],{"class":239},"2",[211,335,243],{"class":216},[211,337,339,342,345],{"class":80,"line":338},6,[211,340,341],{"class":216},"ax.set_title(",[211,343,344],{"class":227},"\"Revenue by month\"",[211,346,243],{"class":216},[211,348,350,353,355],{"class":80,"line":349},7,[211,351,352],{"class":216},"ax.set_ylabel(",[211,354,263],{"class":227},[211,356,243],{"class":216},[211,358,360,363,366,368,371,373,376,378,381],{"class":80,"line":359},8,[211,361,362],{"class":216},"ax.grid(",[211,364,365],{"class":233},"axis",[211,367,221],{"class":220},[211,369,370],{"class":227},"\"y\"",[211,372,176],{"class":216},[211,374,375],{"class":233},"alpha",[211,377,221],{"class":220},[211,379,380],{"class":239},"0.3",[211,382,243],{"class":216},[211,384,386],{"class":80,"line":385},9,[211,387,388],{"class":216},"fig.tight_layout()\n",[211,390,392],{"class":80,"line":391},10,[211,393,394],{"class":216},"fig\n",[10,396,397,398,401,402,405],{},"Returning ",[14,399,400],{},"fig"," explicitly is the habit worth forming. Plotting calls also leave a \"current figure\" behind that\nExcel can pick up, but a formula that builds two figures, or that ends with a line that is not the plot, can\nreturn something other than the chart you meant. ",[14,403,404],{},"fig.tight_layout()"," stops axis labels from being clipped at the\nimage edges, which is otherwise the most common cosmetic defect.",[155,407,409],{"id":408},"step-2-show-the-image-over-the-grid-or-inside-the-cell","Step 2 — Show the image over the grid or inside the cell",[10,411,412,413,416],{},"By default the formula returns an ",[414,415,117],"strong",{},": the cell shows a small image icon and the plot is not yet\nvisible at a useful size. There are two ways to display it.",[160,418,419,429],{},[163,420,421,424,425,428],{},[414,422,423],{},"Display Plot over Cells"," — right-click the cell and choose it from the menu, or press ",[414,426,427],{},"Ctrl+Alt+Shift+C",".\nExcel places a copy of the image floating over the sheet, where you can drag it and resize it from its corners.",[163,430,431,434,435,438,439,442],{},[414,432,433],{},"Excel Value"," — switch the output type from the ",[414,436,437],{},"Python output"," menu next to the formula bar (or with\n",[414,440,441],{},"Ctrl+Alt+Shift+M","). The image is then drawn inside the cell itself and scales with the cell, so widen the\ncolumn, increase the row height or merge cells to make it bigger.",[33,444,42,449,42,452,42,455,42,458,42,462,42,467,42,473,42,477,42,481,42,484,42,488,42,491,42,496,42,500,42,503,42,506,42,508,42,511],{"viewBox":445,"role":36,"ariaLabelledBy":446,"xmlns":40,"style":41},"0 0 760 214",[447,448],"plt-display-t","plt-display-d",[44,450,451],{"id":447},"Two ways to display a Python chart",[48,453,454],{"id":448},"Display Plot over Cells creates a floating copy that can be moved and resized freely. Converting to an Excel value draws the image inside the cell, where it resizes with the cell and moves with sorting and row changes.",[52,456],{"x":54,"y":54,"width":55,"height":457,"fill":57},"214",[52,459],{"x":60,"y":60,"width":460,"height":61,"rx":461,"fill":94,"stroke":85,"style":66},"350","14",[68,463,423],{"x":464,"y":465,"style":466},"195","46","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle",[80,468],{"x1":469,"y1":470,"x2":471,"y2":470,"stroke":85,"style":472},"36","56","354","stroke-width:1px",[68,474,476],{"x":464,"y":475,"style":102},"78","floating copy of the image",[68,478,480],{"x":464,"y":479,"style":102},"101","drag and resize freely",[68,482,427],{"x":464,"y":483,"style":102},"124",[68,485,487],{"x":464,"y":486,"style":102},"147","good for dashboards",[52,489],{"x":490,"y":60,"width":460,"height":61,"rx":461,"fill":135,"stroke":136,"style":66},"390",[68,492,495],{"x":493,"y":465,"style":494},"565","font-size:13px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Excel Value (in cell)",[80,497],{"x1":498,"y1":470,"x2":499,"y2":470,"stroke":136,"style":472},"406","724",[68,501,502],{"x":493,"y":475,"style":102},"image drawn inside the cell",[68,504,505],{"x":493,"y":479,"style":102},"sized by the cell or merge",[68,507,441],{"x":493,"y":483,"style":102},[68,509,510],{"x":493,"y":486,"style":102},"good for tables of charts",[68,512,514],{"x":150,"y":513,"style":152},"200","in-cell images line up with the grid; floating ones do not",[10,516,517],{},"In-cell images suit a layout where each row has its own small chart — a sparkline-style trend next to each\nregion, for example — because the image stays attached to its cell. A floating copy suits a dashboard where one\nlarge chart should sit in a specific position.",[155,519,521],{"id":520},"step-3-size-and-style-for-the-grid","Step 3 — Size and style for the grid",[10,523,524,525,527],{},"A cell-sized image is small, so charts need to be designed for that. Set ",[14,526,293],{}," to the aspect ratio of the space\nthe chart will occupy, raise the DPI modestly so text stays crisp when Excel scales the image, and strip anything that\ndoes not carry information.",[202,529,531],{"className":204,"code":530,"language":206,"meta":207,"style":207},"sales = xl(\"Sales[#All]\", headers=True)\nby_region = sales.groupby(\"Region\")[\"Amount\"].sum().sort_values()\n\nfig, ax = plt.subplots(figsize=(4.5, 2.4), dpi=150)\nbars = ax.barh(by_region.index, by_region.values, color=\"#5b5cf0\")\nax.bar_label(bars, labels=[f\"{v:,.0f}\" for v in by_region.values], padding=3, fontsize=8)\nax.spines[[\"top\", \"right\"]].set_visible(False)\nax.tick_params(labelsize=8)\nax.set_xlim(0, by_region.max() * 1.18)\nax.set_title(\"Revenue by region\", fontsize=10, loc=\"left\")\nfig.tight_layout()\nfig\n",[14,532,533,553,573,577,611,631,697,718,732,750,778,783],{"__ignoreMap":207},[211,534,535,537,539,541,543,545,547,549,551],{"class":80,"line":213},[211,536,217],{"class":216},[211,538,221],{"class":220},[211,540,224],{"class":216},[211,542,228],{"class":227},[211,544,176],{"class":216},[211,546,234],{"class":233},[211,548,221],{"class":220},[211,550,240],{"class":239},[211,552,243],{"class":216},[211,554,555,558,560,563,566,568,570],{"class":80,"line":246},[211,556,557],{"class":216},"by_region ",[211,559,221],{"class":220},[211,561,562],{"class":216}," sales.groupby(",[211,564,565],{"class":227},"\"Region\"",[211,567,260],{"class":216},[211,569,263],{"class":227},[211,571,572],{"class":216},"].sum().sort_values()\n",[211,574,575],{"class":80,"line":275},[211,576,279],{"emptyLinePlaceholder":278},[211,578,579,581,583,585,587,589,591,594,596,599,602,605,607,609],{"class":80,"line":282},[211,580,285],{"class":216},[211,582,221],{"class":220},[211,584,290],{"class":216},[211,586,293],{"class":233},[211,588,221],{"class":220},[211,590,298],{"class":216},[211,592,593],{"class":239},"4.5",[211,595,176],{"class":216},[211,597,598],{"class":239},"2.4",[211,600,601],{"class":216},"), ",[211,603,604],{"class":233},"dpi",[211,606,221],{"class":220},[211,608,61],{"class":239},[211,610,243],{"class":216},[211,612,613,616,618,621,624,626,629],{"class":80,"line":312},[211,614,615],{"class":216},"bars ",[211,617,221],{"class":220},[211,619,620],{"class":216}," ax.barh(by_region.index, by_region.values, ",[211,622,623],{"class":233},"color",[211,625,221],{"class":220},[211,627,628],{"class":227},"\"#5b5cf0\"",[211,630,243],{"class":216},[211,632,633,636,639,641,644,647,650,654,657,660,663,665,668,671,674,677,680,682,685,687,690,692,695],{"class":80,"line":338},[211,634,635],{"class":216},"ax.bar_label(bars, ",[211,637,638],{"class":233},"labels",[211,640,221],{"class":220},[211,642,643],{"class":216},"[",[211,645,646],{"class":220},"f",[211,648,649],{"class":227},"\"",[211,651,653],{"class":652},"sSjpA","{",[211,655,656],{"class":216},"v",[211,658,659],{"class":220},":,.0f",[211,661,662],{"class":652},"}",[211,664,649],{"class":227},[211,666,667],{"class":220}," for",[211,669,670],{"class":216}," v ",[211,672,673],{"class":220},"in",[211,675,676],{"class":216}," by_region.values], ",[211,678,679],{"class":233},"padding",[211,681,221],{"class":220},[211,683,684],{"class":239},"3",[211,686,176],{"class":216},[211,688,689],{"class":233},"fontsize",[211,691,221],{"class":220},[211,693,694],{"class":239},"8",[211,696,243],{"class":216},[211,698,699,702,705,707,710,713,716],{"class":80,"line":349},[211,700,701],{"class":216},"ax.spines[[",[211,703,704],{"class":227},"\"top\"",[211,706,176],{"class":216},[211,708,709],{"class":227},"\"right\"",[211,711,712],{"class":216},"]].set_visible(",[211,714,715],{"class":239},"False",[211,717,243],{"class":216},[211,719,720,723,726,728,730],{"class":80,"line":359},[211,721,722],{"class":216},"ax.tick_params(",[211,724,725],{"class":233},"labelsize",[211,727,221],{"class":220},[211,729,694],{"class":239},[211,731,243],{"class":216},[211,733,734,737,739,742,745,748],{"class":80,"line":385},[211,735,736],{"class":216},"ax.set_xlim(",[211,738,54],{"class":239},[211,740,741],{"class":216},", by_region.max() ",[211,743,744],{"class":220},"*",[211,746,747],{"class":239}," 1.18",[211,749,243],{"class":216},[211,751,752,754,757,759,761,763,766,768,771,773,776],{"class":80,"line":391},[211,753,341],{"class":216},[211,755,756],{"class":227},"\"Revenue by region\"",[211,758,176],{"class":216},[211,760,689],{"class":233},[211,762,221],{"class":220},[211,764,765],{"class":239},"10",[211,767,176],{"class":216},[211,769,770],{"class":233},"loc",[211,772,221],{"class":220},[211,774,775],{"class":227},"\"left\"",[211,777,243],{"class":216},[211,779,781],{"class":80,"line":780},11,[211,782,388],{"class":216},[211,784,786],{"class":80,"line":785},12,[211,787,394],{"class":216},[10,789,790,791,794,795,798,799,801,802,806],{},"Direct value labels with ",[14,792,793],{},"bar_label"," replace the axis ticks a reader would otherwise squint at, and ",[14,796,797],{},"set_xlim"," leaves\nroom for the longest label. A consistent ",[14,800,293],{}," and DPI across every chart in a workbook makes the images line up\nwhen they are placed side by side, in the same way a shared style does in\n",[27,803,805],{"href":804},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fapply-a-reusable-style-theme-across-an-excel-report\u002F","Apply a Reusable Style Theme Across an Excel Report",".",[155,808,810],{"id":809},"step-4-use-seaborn-for-statistical-charts-and-small-multiples","Step 4 — Use seaborn for statistical charts and small multiples",[10,812,813,814,817],{},"The charts Excel cannot draw are where Python in Excel is most worth its cost. seaborn builds a grid of panels —\none per region — or a distribution with a fitted density in a single call, and its figure-level functions return an\nobject whose ",[14,815,816],{},".figure"," attribute is the matplotlib figure to return.",[202,819,821],{"className":204,"code":820,"language":206,"meta":207,"style":207},"sales = xl(\"Sales[#All]\", headers=True)\nsales[\"Month\"] = sales[\"Date\"].dt.to_period(\"M\").dt.to_timestamp()\nmonthly = sales.groupby([\"Region\", \"Month\"], as_index=False)[\"Amount\"].sum()\n\ngrid = sns.relplot(\n    data=monthly, x=\"Month\", y=\"Amount\", col=\"Region\",\n    kind=\"line\", marker=\"o\", height=2.4, aspect=1.2,\n)\ngrid.set_titles(\"{col_name}\")\ngrid.set_axis_labels(\"\", \"Amount\")\nfor ax in grid.axes.flat:\n    ax.tick_params(axis=\"x\", labelrotation=45, labelsize=7)\ngrid.figure.tight_layout()\ngrid.figure\n",[14,822,823,843,870,902,906,916,954,993,997,1011,1025,1038,1071,1077],{"__ignoreMap":207},[211,824,825,827,829,831,833,835,837,839,841],{"class":80,"line":213},[211,826,217],{"class":216},[211,828,221],{"class":220},[211,830,224],{"class":216},[211,832,228],{"class":227},[211,834,176],{"class":216},[211,836,234],{"class":233},[211,838,221],{"class":220},[211,840,240],{"class":239},[211,842,243],{"class":216},[211,844,845,848,851,854,856,859,861,864,867],{"class":80,"line":246},[211,846,847],{"class":216},"sales[",[211,849,850],{"class":227},"\"Month\"",[211,852,853],{"class":216},"] ",[211,855,221],{"class":220},[211,857,858],{"class":216}," sales[",[211,860,257],{"class":227},[211,862,863],{"class":216},"].dt.to_period(",[211,865,866],{"class":227},"\"M\"",[211,868,869],{"class":216},").dt.to_timestamp()\n",[211,871,872,874,876,879,881,883,885,888,891,893,895,897,899],{"class":80,"line":275},[211,873,249],{"class":216},[211,875,221],{"class":220},[211,877,878],{"class":216}," sales.groupby([",[211,880,565],{"class":227},[211,882,176],{"class":216},[211,884,850],{"class":227},[211,886,887],{"class":216},"], ",[211,889,890],{"class":233},"as_index",[211,892,221],{"class":220},[211,894,715],{"class":239},[211,896,260],{"class":216},[211,898,263],{"class":227},[211,900,901],{"class":216},"].sum()\n",[211,903,904],{"class":80,"line":282},[211,905,279],{"emptyLinePlaceholder":278},[211,907,908,911,913],{"class":80,"line":312},[211,909,910],{"class":216},"grid ",[211,912,221],{"class":220},[211,914,915],{"class":216}," sns.relplot(\n",[211,917,918,921,923,926,929,931,933,935,938,940,942,944,947,949,951],{"class":80,"line":338},[211,919,920],{"class":233},"    data",[211,922,221],{"class":220},[211,924,925],{"class":216},"monthly, ",[211,927,928],{"class":233},"x",[211,930,221],{"class":220},[211,932,850],{"class":227},[211,934,176],{"class":216},[211,936,937],{"class":233},"y",[211,939,221],{"class":220},[211,941,263],{"class":227},[211,943,176],{"class":216},[211,945,946],{"class":233},"col",[211,948,221],{"class":220},[211,950,565],{"class":227},[211,952,953],{"class":216},",\n",[211,955,956,959,961,964,966,968,970,972,974,977,979,981,983,986,988,991],{"class":80,"line":349},[211,957,958],{"class":233},"    kind",[211,960,221],{"class":220},[211,962,963],{"class":227},"\"line\"",[211,965,176],{"class":216},[211,967,318],{"class":233},[211,969,221],{"class":220},[211,971,323],{"class":227},[211,973,176],{"class":216},[211,975,976],{"class":233},"height",[211,978,221],{"class":220},[211,980,598],{"class":239},[211,982,176],{"class":216},[211,984,985],{"class":233},"aspect",[211,987,221],{"class":220},[211,989,990],{"class":239},"1.2",[211,992,953],{"class":216},[211,994,995],{"class":80,"line":359},[211,996,243],{"class":216},[211,998,999,1002,1004,1007,1009],{"class":80,"line":385},[211,1000,1001],{"class":216},"grid.set_titles(",[211,1003,649],{"class":227},[211,1005,1006],{"class":652},"{col_name}",[211,1008,649],{"class":227},[211,1010,243],{"class":216},[211,1012,1013,1016,1019,1021,1023],{"class":80,"line":391},[211,1014,1015],{"class":216},"grid.set_axis_labels(",[211,1017,1018],{"class":227},"\"\"",[211,1020,176],{"class":216},[211,1022,263],{"class":227},[211,1024,243],{"class":216},[211,1026,1027,1030,1033,1035],{"class":80,"line":780},[211,1028,1029],{"class":220},"for",[211,1031,1032],{"class":216}," ax ",[211,1034,673],{"class":220},[211,1036,1037],{"class":216}," grid.axes.flat:\n",[211,1039,1040,1043,1045,1047,1050,1052,1055,1057,1060,1062,1064,1066,1069],{"class":80,"line":785},[211,1041,1042],{"class":216},"    ax.tick_params(",[211,1044,365],{"class":233},[211,1046,221],{"class":220},[211,1048,1049],{"class":227},"\"x\"",[211,1051,176],{"class":216},[211,1053,1054],{"class":233},"labelrotation",[211,1056,221],{"class":220},[211,1058,1059],{"class":239},"45",[211,1061,176],{"class":216},[211,1063,725],{"class":233},[211,1065,221],{"class":220},[211,1067,1068],{"class":239},"7",[211,1070,243],{"class":216},[211,1072,1074],{"class":80,"line":1073},13,[211,1075,1076],{"class":216},"grid.figure.tight_layout()\n",[211,1078,1080],{"class":80,"line":1079},14,[211,1081,1082],{"class":216},"grid.figure\n",[10,1084,1085,1086,1088,1089,1092,1093,1096],{},"A small-multiples chart like this replaces a dozen separate Excel charts, and it redraws automatically when the\n",[14,1087,171],{}," table changes. For a distribution, ",[14,1090,1091],{},"sns.histplot(data=sales, x=\"Amount\", hue=\"Region\", kde=True)"," returns\naxes; take ",[14,1094,1095],{},"ax.figure"," from it in the same way.",[33,1098,42,1104,42,1107,42,1110,42,1114,42,1119,42,1123,42,1129,42,1134,42,1141,42,1146,42,1149,42,1153,42,1156,42,1159,42,1163,42,1166,42,1170,42,1173,42,1179,42,1183,42,1186,42,1190,42,1193,42,1199,42,1202],{"viewBox":1099,"role":36,"ariaLabelledBy":1100,"xmlns":40,"style":1103},"0 0 720 256",[1101,1102],"plt-gap-t","plt-gap-d","width:100%;max-width:720px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[44,1105,1106],{"id":1101},"Chart types by how well each tool handles them",[48,1108,1109],{"id":1102},"Simple bar and line charts are easy in native Excel charts. Small multiples, distribution plots with density curves and regression bands are either awkward or impossible natively and straightforward with seaborn.",[52,1111],{"x":54,"y":54,"width":1112,"height":1113,"fill":57},"720","256",[68,1115,1118],{"x":60,"y":1116,"style":1117},"30","font-size:12px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:start","effort in native Excel charts, relative",[52,1120],{"x":60,"y":465,"width":1121,"height":1122,"rx":301,"fill":57,"stroke":65,"style":472},"170","28",[68,1124,1128],{"x":1125,"y":1126,"style":1127},"105","65","font-size:12px;font-weight:600;fill:var(--text,#172033);text-anchor:middle","bar or line",[52,1130],{"x":84,"y":1131,"width":1132,"height":1133,"rx":301,"fill":64,"stroke":65,"style":472},"47","330","26",[52,1135],{"x":1136,"y":1137,"width":1138,"height":1139,"rx":1140,"fill":135,"stroke":136,"style":472},"205","48","47.5","24","5",[68,1142,1145],{"x":1143,"y":1126,"style":1144},"546","font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:start","easy natively",[52,1147],{"x":60,"y":1148,"width":1121,"height":1122,"rx":301,"fill":57,"stroke":65,"style":472},"90",[68,1150,1152],{"x":1125,"y":1151,"style":1127},"109","combo, 2 axes",[52,1154],{"x":84,"y":1155,"width":1132,"height":1133,"rx":301,"fill":64,"stroke":65,"style":472},"91",[52,1157],{"x":1136,"y":123,"width":1158,"height":1139,"rx":1140,"fill":94,"stroke":85,"style":472},"130",[68,1160,1162],{"x":1143,"y":1151,"style":1161},"font-size:12px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:start","manageable",[52,1164],{"x":60,"y":1165,"width":1121,"height":1122,"rx":301,"fill":57,"stroke":65,"style":472},"134",[68,1167,1169],{"x":1125,"y":1168,"style":1127},"153","small multiples",[52,1171],{"x":84,"y":1172,"width":1132,"height":1133,"rx":301,"fill":64,"stroke":65,"style":472},"135",[52,1174],{"x":1136,"y":1175,"width":1176,"height":1139,"rx":1140,"fill":1177,"stroke":1178,"style":472},"136","278.5","#fdefd8","var(--gold,#b4740a)",[68,1180,1182],{"x":1143,"y":1168,"style":1181},"font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:start","use seaborn",[52,1184],{"x":60,"y":1185,"width":1121,"height":1122,"rx":301,"fill":57,"stroke":65,"style":472},"178",[68,1187,1189],{"x":1125,"y":1188,"style":1127},"197","density, regression",[52,1191],{"x":84,"y":1192,"width":1132,"height":1133,"rx":301,"fill":64,"stroke":65,"style":472},"179",[52,1194],{"x":1136,"y":1195,"width":1196,"height":1139,"rx":1140,"fill":1197,"stroke":1198,"style":472},"180","311.5","#fee8f2","var(--accent,#f43f8f)",[68,1200,1182],{"x":1143,"y":1188,"style":1201},"font-size:12px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:start",[68,1203,1206],{"x":1204,"y":1205,"style":152},"360","238","reach for Python where the native gallery stops",[155,1208,1210],{"id":1209},"step-5-know-when-a-native-excel-chart-is-better","Step 5 — Know when a native Excel chart is better",[10,1212,1213],{},"A Python chart is an image. That makes it the wrong tool in a few common situations: when readers need to hover for\nvalues or filter series, when the workbook must work offline or for people without Python in Excel, and when a chart\nshould update instantly while someone types. In those cases, let Python compute and spill the numbers as Excel values,\nand build a native chart on the spilled range.",[202,1215,1217],{"className":204,"code":1216,"language":206,"meta":207,"style":207},"sales = xl(\"Sales[#All]\", headers=True)\n(\n    sales.pivot_table(index=sales[\"Date\"].dt.to_period(\"M\").astype(str),\n                      columns=\"Region\", values=\"Amount\", aggfunc=\"sum\", fill_value=0)\n         .rename_axis(\"Month\")\n         .reset_index()\n)\n",[14,1218,1219,1239,1244,1271,1310,1319,1324],{"__ignoreMap":207},[211,1220,1221,1223,1225,1227,1229,1231,1233,1235,1237],{"class":80,"line":213},[211,1222,217],{"class":216},[211,1224,221],{"class":220},[211,1226,224],{"class":216},[211,1228,228],{"class":227},[211,1230,176],{"class":216},[211,1232,234],{"class":233},[211,1234,221],{"class":220},[211,1236,240],{"class":239},[211,1238,243],{"class":216},[211,1240,1241],{"class":80,"line":246},[211,1242,1243],{"class":216},"(\n",[211,1245,1246,1249,1252,1254,1256,1258,1260,1262,1265,1268],{"class":80,"line":275},[211,1247,1248],{"class":216},"    sales.pivot_table(",[211,1250,1251],{"class":233},"index",[211,1253,221],{"class":220},[211,1255,847],{"class":216},[211,1257,257],{"class":227},[211,1259,863],{"class":216},[211,1261,866],{"class":227},[211,1263,1264],{"class":216},").astype(",[211,1266,1267],{"class":239},"str",[211,1269,1270],{"class":216},"),\n",[211,1272,1273,1276,1278,1280,1282,1285,1287,1289,1291,1294,1296,1299,1301,1304,1306,1308],{"class":80,"line":282},[211,1274,1275],{"class":233},"                      columns",[211,1277,221],{"class":220},[211,1279,565],{"class":227},[211,1281,176],{"class":216},[211,1283,1284],{"class":233},"values",[211,1286,221],{"class":220},[211,1288,263],{"class":227},[211,1290,176],{"class":216},[211,1292,1293],{"class":233},"aggfunc",[211,1295,221],{"class":220},[211,1297,1298],{"class":227},"\"sum\"",[211,1300,176],{"class":216},[211,1302,1303],{"class":233},"fill_value",[211,1305,221],{"class":220},[211,1307,54],{"class":239},[211,1309,243],{"class":216},[211,1311,1312,1315,1317],{"class":80,"line":312},[211,1313,1314],{"class":216},"         .rename_axis(",[211,1316,850],{"class":227},[211,1318,243],{"class":216},[211,1320,1321],{"class":80,"line":338},[211,1322,1323],{"class":216},"         .reset_index()\n",[211,1325,1326],{"class":80,"line":349},[211,1327,243],{"class":216},[10,1329,1330,1331,1334,1335,806],{},"Set this formula's output to ",[414,1332,1333],{},"Excel value",", select the spilled block, and insert a line chart. Python does the\nreshaping that would otherwise need a helper pivot table; Excel draws a chart that is interactive and needs no cloud\nround trip to repaint. The same \"compute in Python, chart natively\" split is how scripts produce charts in files, as in\n",[27,1336,1338],{"href":1337},"\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",[155,1340,1342],{"id":1341},"step-6-build-a-row-of-trend-images-with-a-helper-function","Step 6 — Build a row of trend images with a helper function",[10,1344,1345],{},"In-cell images become powerful when each row of a summary table carries its own small trend: region in column A,\ntotal in column B, and a tiny line chart in column C. Writing the same plotting code twelve times would be fragile, so\ndefine a helper once in an early cell and call it from one short formula per row.",[202,1347,1349],{"className":204,"code":1348,"language":206,"meta":207,"style":207},"# Cell A1 (top of the first sheet) — shared data and a plotting helper\nsales = xl(\"Sales[#All]\", headers=True)\nmonthly_by_region = (\n    sales.assign(Month=sales[\"Date\"].dt.to_period(\"M\").dt.to_timestamp())\n         .groupby([\"Region\", \"Month\"])[\"Amount\"].sum()\n)\n\ndef trend(region: str):\n    series = monthly_by_region.loc[region]\n    fig, ax = plt.subplots(figsize=(2.4, 0.7), dpi=150)\n    ax.plot(series.index, series.values, linewidth=1.6, color=\"#0f9488\")\n    ax.fill_between(series.index, series.values, alpha=0.15, color=\"#0f9488\")\n    ax.scatter(series.index[-1], series.values[-1], s=12, color=\"#0f9488\", zorder=3)\n    ax.axis(\"off\")\n    fig.tight_layout(pad=0.1)\n    return fig\n\n\"helpers ready\"\n",[14,1350,1351,1357,1377,1387,1408,1426,1430,1434,1451,1461,1493,1516,1538,1584,1594,1610,1619,1624],{"__ignoreMap":207},[211,1352,1353],{"class":80,"line":213},[211,1354,1356],{"class":1355},"s-wDw","# Cell A1 (top of the first sheet) — shared data and a plotting helper\n",[211,1358,1359,1361,1363,1365,1367,1369,1371,1373,1375],{"class":80,"line":246},[211,1360,217],{"class":216},[211,1362,221],{"class":220},[211,1364,224],{"class":216},[211,1366,228],{"class":227},[211,1368,176],{"class":216},[211,1370,234],{"class":233},[211,1372,221],{"class":220},[211,1374,240],{"class":239},[211,1376,243],{"class":216},[211,1378,1379,1382,1384],{"class":80,"line":275},[211,1380,1381],{"class":216},"monthly_by_region ",[211,1383,221],{"class":220},[211,1385,1386],{"class":216}," (\n",[211,1388,1389,1392,1395,1397,1399,1401,1403,1405],{"class":80,"line":282},[211,1390,1391],{"class":216},"    sales.assign(",[211,1393,1394],{"class":233},"Month",[211,1396,221],{"class":220},[211,1398,847],{"class":216},[211,1400,257],{"class":227},[211,1402,863],{"class":216},[211,1404,866],{"class":227},[211,1406,1407],{"class":216},").dt.to_timestamp())\n",[211,1409,1410,1413,1415,1417,1419,1422,1424],{"class":80,"line":312},[211,1411,1412],{"class":216},"         .groupby([",[211,1414,565],{"class":227},[211,1416,176],{"class":216},[211,1418,850],{"class":227},[211,1420,1421],{"class":216},"])[",[211,1423,263],{"class":227},[211,1425,901],{"class":216},[211,1427,1428],{"class":80,"line":338},[211,1429,243],{"class":216},[211,1431,1432],{"class":80,"line":349},[211,1433,279],{"emptyLinePlaceholder":278},[211,1435,1436,1439,1443,1446,1448],{"class":80,"line":359},[211,1437,1438],{"class":220},"def",[211,1440,1442],{"class":1441},"s_Opv"," trend",[211,1444,1445],{"class":216},"(region: ",[211,1447,1267],{"class":239},[211,1449,1450],{"class":216},"):\n",[211,1452,1453,1456,1458],{"class":80,"line":385},[211,1454,1455],{"class":216},"    series ",[211,1457,221],{"class":220},[211,1459,1460],{"class":216}," monthly_by_region.loc[region]\n",[211,1462,1463,1466,1468,1470,1472,1474,1476,1478,1480,1483,1485,1487,1489,1491],{"class":80,"line":391},[211,1464,1465],{"class":216},"    fig, ax ",[211,1467,221],{"class":220},[211,1469,290],{"class":216},[211,1471,293],{"class":233},[211,1473,221],{"class":220},[211,1475,298],{"class":216},[211,1477,598],{"class":239},[211,1479,176],{"class":216},[211,1481,1482],{"class":239},"0.7",[211,1484,601],{"class":216},[211,1486,604],{"class":233},[211,1488,221],{"class":220},[211,1490,61],{"class":239},[211,1492,243],{"class":216},[211,1494,1495,1498,1500,1502,1505,1507,1509,1511,1514],{"class":80,"line":780},[211,1496,1497],{"class":216},"    ax.plot(series.index, series.values, ",[211,1499,328],{"class":233},[211,1501,221],{"class":220},[211,1503,1504],{"class":239},"1.6",[211,1506,176],{"class":216},[211,1508,623],{"class":233},[211,1510,221],{"class":220},[211,1512,1513],{"class":227},"\"#0f9488\"",[211,1515,243],{"class":216},[211,1517,1518,1521,1523,1525,1528,1530,1532,1534,1536],{"class":80,"line":785},[211,1519,1520],{"class":216},"    ax.fill_between(series.index, series.values, ",[211,1522,375],{"class":233},[211,1524,221],{"class":220},[211,1526,1527],{"class":239},"0.15",[211,1529,176],{"class":216},[211,1531,623],{"class":233},[211,1533,221],{"class":220},[211,1535,1513],{"class":227},[211,1537,243],{"class":216},[211,1539,1540,1543,1546,1549,1552,1554,1556,1558,1561,1563,1565,1567,1569,1571,1573,1575,1578,1580,1582],{"class":80,"line":1073},[211,1541,1542],{"class":216},"    ax.scatter(series.index[",[211,1544,1545],{"class":220},"-",[211,1547,1548],{"class":239},"1",[211,1550,1551],{"class":216},"], series.values[",[211,1553,1545],{"class":220},[211,1555,1548],{"class":239},[211,1557,887],{"class":216},[211,1559,1560],{"class":233},"s",[211,1562,221],{"class":220},[211,1564,63],{"class":239},[211,1566,176],{"class":216},[211,1568,623],{"class":233},[211,1570,221],{"class":220},[211,1572,1513],{"class":227},[211,1574,176],{"class":216},[211,1576,1577],{"class":233},"zorder",[211,1579,221],{"class":220},[211,1581,684],{"class":239},[211,1583,243],{"class":216},[211,1585,1586,1589,1592],{"class":80,"line":1079},[211,1587,1588],{"class":216},"    ax.axis(",[211,1590,1591],{"class":227},"\"off\"",[211,1593,243],{"class":216},[211,1595,1597,1600,1603,1605,1608],{"class":80,"line":1596},15,[211,1598,1599],{"class":216},"    fig.tight_layout(",[211,1601,1602],{"class":233},"pad",[211,1604,221],{"class":220},[211,1606,1607],{"class":239},"0.1",[211,1609,243],{"class":216},[211,1611,1613,1616],{"class":80,"line":1612},16,[211,1614,1615],{"class":220},"    return",[211,1617,1618],{"class":216}," fig\n",[211,1620,1622],{"class":80,"line":1621},17,[211,1623,279],{"emptyLinePlaceholder":278},[211,1625,1627],{"class":80,"line":1626},18,[211,1628,1629],{"class":227},"\"helpers ready\"\n",[202,1631,1633],{"className":204,"code":1632,"language":206,"meta":207,"style":207},"# Cell C5 — one formula per row; A5 holds the region name as ordinary text\ntrend(xl(\"A5\"))\n",[14,1634,1635,1640],{"__ignoreMap":207},[211,1636,1637],{"class":80,"line":213},[211,1638,1639],{"class":1355},"# Cell C5 — one formula per row; A5 holds the region name as ordinary text\n",[211,1641,1642,1645,1648],{"class":80,"line":246},[211,1643,1644],{"class":216},"trend(xl(",[211,1646,1647],{"class":227},"\"A5\"",[211,1649,309],{"class":216},[10,1651,1652,1653,1655,1656,1659,1660,1663],{},"Set each trend cell's output to ",[414,1654,433],{}," so the image sits inside it, then give the column a fixed width and\nthe rows a fixed height so every chart has the same proportions. ",[14,1657,1658],{},"ax.axis(\"off\")"," removes ticks and frames, which are\nunreadable at this size anyway, and the dot on the last point draws the eye to the current value. Because the helper\nreads from ",[14,1661,1662],{},"monthly_by_region",", the data is aggregated once rather than once per row — and because the calculation\norder runs across each row and down, the helper in row 1 always exists before row 5 needs it.",[155,1665,1667],{"id":1666},"common-pitfalls","Common pitfalls",[1669,1670,1671,1687],"table",{},[1672,1673,1674],"thead",{},[1675,1676,1677,1681,1684],"tr",{},[1678,1679,1680],"th",{},"Symptom",[1678,1682,1683],{},"Cause",[1678,1685,1686],{},"Fix",[1688,1689,1690,1702,1716,1730,1747,1758],"tbody",{},[1675,1691,1692,1696,1699],{},[1693,1694,1695],"td",{},"Cell shows an image icon, no visible chart",[1693,1697,1698],{},"Default image-object output",[1693,1700,1701],{},"Display Plot over Cells, or switch to Excel Value",[1675,1703,1704,1707,1710],{},[1693,1705,1706],{},"Labels cut off at the edges",[1693,1708,1709],{},"Figure laid out without margins",[1693,1711,1712,1713,1715],{},"Call ",[14,1714,404],{}," before returning",[1675,1717,1718,1721,1724],{},[1693,1719,1720],{},"Wrong chart returned",[1693,1722,1723],{},"Formula made several figures, or ended on another line",[1693,1725,1726,1727,1729],{},"Return the intended ",[14,1728,400],{}," as the last expression",[1675,1731,1732,1735,1738],{},[1693,1733,1734],{},"Text unreadable in a cell-sized image",[1693,1736,1737],{},"Default figure size and DPI",[1693,1739,1740,1741,176,1743,1746],{},"Smaller ",[14,1742,293],{},[14,1744,1745],{},"dpi=150",", larger fonts",[1675,1748,1749,1752,1755],{},[1693,1750,1751],{},"Floating chart shows old data",[1693,1753,1754],{},"It is a copy of the image",[1693,1756,1757],{},"Display it again after recalculation, or use the in-cell image",[1675,1759,1760,1763,1766],{},[1693,1761,1762],{},"seaborn call returns a grid, not a figure",[1693,1764,1765],{},"Figure-level functions return a FacetGrid",[1693,1767,1768,1769],{},"Return ",[14,1770,1771],{},"grid.figure",[155,1773,1775],{"id":1774},"performance-and-scale-notes","Performance and scale notes",[10,1777,1778,1779,1782],{},"Every recalculation redraws the chart in the cloud and sends a new image back, so a sheet with many chart cells\nrecalculates noticeably more slowly than one with a few. Aggregate before plotting — a line of twelve monthly points\ndraws faster and reads better than 50,000 raw points — and switch to ",[414,1780,1781],{},"Partial"," calculation while editing a\nchart-heavy workbook. Remember too that the data behind any single calculation is capped at 100 MB, which a\nrow-level scatter of a very large table can approach.",[155,1784,1786],{"id":1785},"conclusion","Conclusion",[10,1788,1789],{},"Build charts with explicit figures and axes, finish the formula with the figure, and choose the display that suits the\nlayout: a floating copy for a dashboard, an in-cell image for a row-aligned table of charts. Design for the small space\nwith deliberate size, DPI and direct labels. Use seaborn where Excel's gallery runs out — small multiples, distributions\nand statistical overlays — and when a chart must be interactive or work without Python, spill the numbers as Excel values\nand draw a native chart on them.",[155,1791,1793],{"id":1792},"frequently-asked-questions","Frequently asked questions",[10,1795,1796,1799],{},[414,1797,1798],{},"Do I need to import matplotlib or seaborn?","\nNo. Python in Excel imports matplotlib.pyplot as plt and seaborn as sns by default, and lists those imports in the Initialization pane on the Formulas tab.",[10,1801,1802,1805],{},[414,1803,1804],{},"Can I call plt.show()?","\nThere is no window to show a plot in. Return the figure object as the last expression instead; that is what Excel turns into the image.",[10,1807,1808,1811],{},[414,1809,1810],{},"Can I copy a Python chart into PowerPoint?","\nYes. Display the plot over cells, then copy the floating image like any other picture. It is a static image, so it does not update in the presentation.",[10,1813,1814,1817],{},[414,1815,1816],{},"Can I use plotly or other interactive libraries?","\nInteractive output does not carry into the grid, because Excel receives an image. Stick to matplotlib-based libraries for charts in cells.",[155,1819,1821],{"id":1820},"related","Related",[160,1823,1824,1830,1837,1844,1851],{},[163,1825,1826,1827,1829],{},"Up one level: ",[27,1828,30],{"href":29}," — where =PY charts fit among Excel automation options.",[163,1831,1832,1836],{},[27,1833,1835],{"href":1834},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Freturn-dataframes-and-values-from-python-in-excel-cells\u002F","Return DataFrames and Values from Python in Excel Cells"," — output types and spilling in detail.",[163,1838,1839,1843],{},[27,1840,1842],{"href":1841},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-a-matplotlib-chart-in-an-excel-report\u002F","Embed a matplotlib Chart in an Excel Report"," — the same charts, inserted into a file by a script.",[163,1845,1846,1850],{},[27,1847,1849],{"href":1848},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fcreating-charts-in-excel-with-openpyxl\u002F","Creating Charts in Excel with openpyxl"," — native, interactive charts written from Python.",[163,1852,1853,1857],{},[27,1854,1856],{"href":1855},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fpython-in-excel-vs-openpyxl-and-xlwings\u002F","Python in Excel vs openpyxl and xlwings"," — choosing between in-cell Python and scripts.",[1859,1860,1861],"style",{},"html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}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 .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}",{"title":207,"searchDepth":246,"depth":246,"links":1863},[1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875],{"id":157,"depth":246,"text":158},{"id":196,"depth":246,"text":197},{"id":408,"depth":246,"text":409},{"id":520,"depth":246,"text":521},{"id":809,"depth":246,"text":810},{"id":1209,"depth":246,"text":1210},{"id":1341,"depth":246,"text":1342},{"id":1666,"depth":246,"text":1667},{"id":1774,"depth":246,"text":1775},{"id":1785,"depth":246,"text":1786},{"id":1792,"depth":246,"text":1793},{"id":1820,"depth":246,"text":1821},"2026-09-17","Draw matplotlib and seaborn charts inside a =PY cell, show them in the cell or floating over the grid, size them properly, and know when a native Excel chart is the better choice.","md",[1880,1882,1884,1886],{"q":1798,"a":1881},"No. Python in Excel imports matplotlib.pyplot as plt and seaborn as sns by default, and lists those imports in the Initialization pane on the Formulas tab.",{"q":1804,"a":1883},"There is no window to show a plot in. Return the figure object as the last expression instead; that is what Excel turns into the image.",{"q":1810,"a":1885},"Yes. Display the plot over cells, then copy the floating image like any other picture. It is a static image, so it does not update in the presentation.",{"q":1816,"a":1887},"Interactive output does not carry into the grid, because Excel receives an image. Stick to matplotlib-based libraries for charts in cells.","plot charts with matplotlib in python in excel",null,{"breadcrumb":1891},[1892,1895,1898],{"name":1893,"item":1894},"Home","\u002F",{"name":1896,"item":1897},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":30,"item":29},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fplot-charts-with-matplotlib-in-python-in-excel",{"title":1901,"description":1902},"Plot Charts with matplotlib and seaborn in Python in Excel","Create matplotlib and seaborn plots with Python in Excel: image objects, Display Plot over Cells, in-cell images, figure size and DPI, small multiples, and native chart alternatives.","plot-charts-with-matplotlib-in-python-in-excel","getting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fplot-charts-with-matplotlib-in-python-in-excel\u002Findex",[1906,1907],"python-in-excel","charts-and-images","how-to","JQGj9v52TpfbtItxx9v-OlXZPCZtZBo3DBJRj8AKu5k",[1911,1915],{"title":1912,"path":1913,"stem":1914,"children":-1},"Get External Data into Python in Excel with Power Query","\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fget-external-data-into-python-in-excel","getting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fget-external-data-into-python-in-excel\u002Findex",{"title":1856,"path":1916,"stem":1917,"children":-1},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fpython-in-excel-vs-openpyxl-and-xlwings","getting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fpython-in-excel-vs-openpyxl-and-xlwings\u002Findex",[1919,1921],{"path":1920,"title":1896},"\u002Fgetting-started-with-python-excel-automation",{"path":1922,"title":30},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel",[],[1925,1928,1932,1935,1936,1938],{"path":1926,"title":1927,"kind":1908},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fclean-data-with-pandas-in-python-in-excel","Clean Data with pandas in Python in Excel",{"path":1929,"title":1930,"kind":1931},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Ffix-python-in-excel-errors","Fix Python in Excel Errors","fix",{"path":1933,"title":1934,"kind":1908},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Fforecast-a-time-series-with-python-in-excel","Forecast a Time Series with Python in Excel",{"path":1913,"title":1912,"kind":1908},{"path":1916,"title":1856,"kind":1937},"compare",{"path":1939,"title":1940,"kind":1908},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-python-in-excel\u002Freference-cells-ranges-and-tables-with-xl-in-python-in-excel","Reference Cells, Ranges and Tables with xl() in Python in Excel",1790972075370]