Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Enhance your career with this limited time 50% discount on Fabric and Power BI exams. Ends August 31st. Request your voucher.

Reply
Flan
New Member

Python visuals doesn't work on online reading view but on desktop does

Hi everyone, 

 

Since a couple of day maybe week, i didn't noticed that one of my own python visual didn't work on the online version. On my dekstop app, nothing, it work well but only when i share the link and open it via my workspace the visual doesn't work anymore. 

there erreur that i have is this one : 

Script Runtime Error

[S-12c5e384-a869-4a16-9c4a-12dd6770c94c][S-12c5e384-a869-4a16-9c4a-12dd6770c94c]AttributeError: 'NoneType' object has no attribute 'points_to_pixels'
Please try again later or contact support. If you contact support, please provide these details.

Activity ID: fb2167c7-a9c2-4229-ba95-dd2df542479d
Request ID: d0f51534-072d-4d2e-a767-651859b64a82
Correlation ID: 101ac569-2fa3-434e-5997-79102e36e5a0
Time: Mon Dec 02 2024 18:25:33 GMT+0100 (Central European Standard Time)
Service version: 13.0.24766.27
Client version: 2411.3.21845-train
Cluster URI: https://wabi-west-europe-b-primary-redirect.analysis.windows.net/

 

 

My code is but i am not sure that it come from him because nothing change since a couple of months... 

import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.dates as mdates
from matplotlib.dates import DateFormatter, MonthLocator

# Supposons que dataset soit un DataFrame pandas déjà défini
dataset['Date update'] = pd.to_datetime(dataset['Date update'])
dataset['Forecast'] = pd.to_datetime(dataset['Forecast'])

# Pivot table
pivot = pd.pivot_table(dataset, aggfunc='first', index='Date update', values='Forecast', columns='Milestones name')
fig, ax = plt.subplots(figsize=(12, 8))

# Plot each column
for column in pivot.columns:
    clean = pivot[[column]].dropna()
    ax.plot_date(clean.index, clean[column], xdate=True, ydate=True, ls='-', lw=1, label=column)

# Ajuster les limites des axes pour découpler Date update (axe x) et Forecast (axe y)
min_date_update = dataset['Date update'].min()
max_date_update = dataset['Date update'].max()

min_forecast = dataset['Forecast'].min()
max_forecast = dataset['Forecast'].max()

# Dates limites pour les axes
max_date_forecast = max(dataset['Forecast'])
next_year_forecast = max_date_forecast.year + 1
q1_next_year_forecast = pd.Timestamp(year=next_year_forecast, month=1, day=1)

min_date_forecast = min(dataset['Forecast'])
min_year_forecast = min_date_forecast.year
q1_actual_year_forecast = pd.Timestamp(year=min_year_forecast, month=1, day=1)

min_date_update = min(dataset['Date update'])
min_year_dateupdate = min_date_update.year
q1_actual_year_dateupdate = pd.Timestamp(year=min_year_dateupdate, month=1, day=1)

# Ajouter la ligne 45 degrés (y=x)
# Créer des listes de dates pour la ligne 45 degrés
line_dates = pd.date_range(start=q1_actual_year_dateupdate, end=q1_next_year_forecast, freq='D')
ax.plot(line_dates, line_dates, color='black', linestyle='--', label='')

# Coloration après les courbes
adjusted_min_date_update = q1_actual_year_dateupdate
adjusted_max_forecast = q1_next_year_forecast
if len(line_dates) > 0:
    ax.fill_between(line_dates, adjusted_min_date_update, line_dates, color='white', zorder=2)

# -----------------------------------------------------------------------------------------------

# Définir les localisateurs pour les mois (trimestres)

month_locator = MonthLocator(bymonth=[1, 4, 7, 10])

plt.gca().xaxis.set_major_locator(month_locator)
plt.gca().yaxis.set_major_locator(month_locator)

# Création du formateur personnalisé pour afficher les trimestres
class QuarterFormatter(DateFormatter):
    def __init__(self, fmt='%Y-%m', **kwargs):
        super().__init__(fmt, **kwargs)

    def __call__(self, x, pos=0):
        date = mdates.num2date(x)
        # Si c'est janvier, afficher l'année en dessous de Q1
        if date.month == 1:
            return f'{date.year} - Q1'
        elif date.month == 4:
            return 'Q2'
        elif date.month == 7:
            return 'Q3'
        elif date.month == 10:
            return 'Q4'
        return ''

# Appliquer le formateur de trimestre personnalisé
quarter_formatter = QuarterFormatter()
plt.gca().xaxis.set_major_formatter(quarter_formatter)
plt.gca().yaxis.set_major_formatter(quarter_formatter)

# -----------------------------------------------------------------------------------------------

# Rotation des étiquettes pour une meilleure lisibilité
plt.xticks(rotation=90, ha='center')

# Ajouter les lignes de grille pour les années uniquement
start_date_update = pd.Timestamp(year=q1_actual_year_dateupdate.year, month=1, day=1)
end_date_forecast = pd.Timestamp(year=q1_next_year_forecast.year, month=1, day=1)
for year in range(start_date_update.year, end_date_forecast.year):
    january_start = pd.Timestamp(year=year, month=1, day=1)
    ax.axvline(x=january_start, color='gray', linestyle='--', linewidth=0.5)
    ax.axhline(y=january_start, color='gray', linestyle='--', linewidth=0.5)

# -----------------------------------------------------------------------------------------------

# Ajuster les limites des axes
plt.xlim(q1_actual_year_dateupdate, q1_next_year_forecast)  # Limites pour l'axe des x (Date update)
plt.ylim(q1_actual_year_dateupdate, q1_next_year_forecast)   # Limites pour l'axe des y (Forecast)

# -----------------------------------------------------------------------------------------------
legend = ax.legend(loc='upper left', bbox_to_anchor=(1.01, 1), frameon=False)
# Ajuster la légende
def adjust_legend_fontsize(ax):
    legend = ax.get_legend()  # Récupère la légende existante
    if legend is None:  # Si aucune légende n'est définie, arrêter
        return 10

    fig = ax.get_window_extent()
    fig_height = fig.height 
    fontsize = 10
    adjusted = False
    while not adjusted:
        legend = ax.legend(loc='upper left', bbox_to_anchor=(1, 1), fontsize=fontsize)
        legend_bbox = legend.get_window_extent()
        legend_height = legend_bbox.height
        if legend_height <= fig_height:
            adjusted = True
        else:
            fontsize -= 1
            if fontsize < 8:
                break
    return fontsize
ax = plt.gca()
fontsize = adjust_legend_fontsize(ax)
myLegend = ax.legend(loc='upper left', bbox_to_anchor=(1.01, 1), frameon=False, fontsize=fontsize)

# Désactiver les ajustements automatiques des marges
plt.subplots_adjust(left=0.08, right=0.75, top=0.95, bottom=0.1)

# Afficher le graphique
plt.show()

 

If you have an idea, that coudl help me !! 
thanks you very much in advance, and have a nice day !

Flan

3 REPLIES 3
lbendlin
Super User
Super User

Maybe read through the release notes of these two libraries - could be that a recent version update has caused that.

Hi ! 
Unfortunately, even with librabries updated, it still doesn't work.
It's weird because others visual work so i guess there is an issue with this one in particular... 😞 

 

If you have a Pro license you can open a Pro ticket at https://admin.powerplatform.microsoft.com/newsupportticket/powerbi
Otherwise you can raise an issue at https://community.fabric.microsoft.com/t5/Issues/idb-p/Issues .

Helpful resources

Announcements
July PBI25 Carousel

Power BI Monthly Update - July 2025

Check out the July 2025 Power BI update to learn about new features.

Join our Fabric User Panel

Join our Fabric User Panel

This is your chance to engage directly with the engineering team behind Fabric and Power BI. Share your experiences and shape the future.

June 2025 community update carousel

Fabric Community Update - June 2025

Find out what's new and trending in the Fabric community.

Top Solution Authors