When generating charts with Matplotlib or Seaborn in Excel, the cell often displays text like <Figure size 640x480 with 1 Axes>, a blank box, or a #PYTHON! error instead of a visible plot. This occurs because Excel has two distinct output modes for Python cells: Python Object and Excel Value.
By default, Excel treats a Matplotlib figure as a generic Python Object rather than converting the canvas into a viewable graphic.
Quick Fix: How to display Matplotlib charts as images
To render a Matplotlib plot as a visible image in Excel, do not return
plt.show(). Instead, finalize your chart usingplt.figure()orplt.subplots(), pass the plot code, and ensure the final evaluated line returns the figure object itself (for example,figorplt.gcf()). Then, set the cell output toggle in the Formula Bar to Excel Value.
The Root Cause: Object Reference vs. Visual Rasterization
Excel’s Python integration can render visual graphics directly inside grid cells, but the rendering pipeline requires two specific conditions:
[ Python Script in =PY() ]
│
├─► Returns plt.show()? ──► Returns None ──► Blank Cell / Error
│
└─► Returns Figure Object (e.g., fig or plt.gcf())
│
▼
[ Cell Output Type Setting ]
│
├─► Set to "Python Object" ──► Displays: [Figure size 640x480...]
│
└─► Set to "Excel Value" ──► Displays: High-Resolution Graphic in Cell
- The script must return a Figure object: Calling
plt.show()outputsNonein the cloud environment. Excel cannot renderNone, resulting in an empty cell. - The cell must be toggled to Excel Value: If the cell output toggle remains set to “Python Object,” Excel shows a card with metadata about the figure canvas rather than rasterizing the plot.
Step-by-Step Fix to Render Plots Correctly
Follow this pattern to render plots reliably across Matplotlib and Seaborn.
Step 1: Write the Code to Return the Figure
Always create an explicit figure handle and return it as the final line of your code:
import matplotlib.pyplot as plt
import seaborn as sns
# Create explicit figure and axis handles
fig, ax = plt.subplots(figsize=(6, 4))
# Generate the plot
df = xl("SalesData[#All]", headers=True)
sns.barplot(data=df, x="Region", y="Revenue", ax=ax)
# Set labels and formatting
ax.set_title("Total Revenue by Region")
plt.tight_layout()
# Return the figure object explicitly
fig
If you use pure procedural plt functions without subplots, return the current figure handle using plt.gcf() (Get Current Figure):
import matplotlib.pyplot as plt
plt.figure(figsize=(6, 4))
plt.plot([1, 2, 3, 4], [10, 20, 25, 30])
plt.title("Growth Rate")
# Return current figure
plt.gcf()
Step 2: Toggle the Cell to Excel Value
After committing the formula (Ctrl + Enter):
- Click on the cell containing the Python formula.
- In the Formula Bar, locate the Python Output Type toggle located to the left of the formula input.
- Switch the selection from Python Object (card icon) to Excel Value (grid icon), or use the keyboard shortcut Ctrl + Shift + Alt + M.
- The cell will recalculate and rasterize the figure directly inside the cell grid.
If you want to understand how Excel handles data types and object properties across cells, review Troubleshooting “Excel Object Conversion”: Python Values vs. Excel Objects..
Fixing Common Matplotlib Rendering Problems
Symptom: Cell is empty
Reason: Code ended with plt.show()
Fix: Replace plt.show() with plt.gcf() or return the explicit fig object.
Symptom: Text shows "<Figure size ...>"
Reason: Cell is set to "Python Object"
Fix: Toggle cell output to "Excel Value" (Ctrl + Shift + Alt + M).
Symptom: Chart appears tiny or unreadable
Reason: Cell row height / column width is too small
Fix: Expand row height and column width, or merge display cells.
Symptom: Chart lines/text look pixelated or blurry
Reason: Standard cloud rasterization DPI settings
Fix: Adjust figure dimensions and DPI explicitly via plt.subplots(dpi=150).
Problem 1: Plots Looking Blurry or Clipped
Because the plot renders inside a cell boundary, standard spreadsheet row heights can compress the visual preview.
- Adjust the cell’s row height and column width to give the image space to expand.
- Alternatively, right-click the image cell and select Picture in Cell > Create Floating Copy to turn the graphic into a floating image shape that can be resized over multiple rows.
For in-depth advice on resolving DPI and blur problems, check Fixing “Plot Scaling” issues: Why Python charts look blurry in Excel..
Problem 2: Overlapping Axes and Text Truncation
In smaller cell windows, axis labels frequently collide. Always call plt.tight_layout() before returning the figure:
fig, ax = plt.subplots(figsize=(7, 3.5))
ax.plot(xl("Timeline[Date]"), xl("Timeline[Visits]"))
plt.xticks(rotation=45)
plt.tight_layout()
fig
Problem 3: State Accumulation Across Recalculations
If multiple cells create procedural plots without resetting the internal state, plots from earlier calculations may bleed into subsequent charts. Clear the figure buffer explicitly when building complex standalone plots:
plt.close('all')
fig, ax = plt.subplots()
# ... plot logic ...
fig
For more assistance with library operations in your sheets, refer to our central guide on Managing Python Libraries in Excel: Fixing Imports and Syntax..