2025, Dec 06 17:00

How to fix pandas AttributeError: 'NoneType' has no attribute 'total_seconds' from win32com Excel pywintypes.datetime

Importing Excel via win32com yields pywintypes.datetime, triggering a pandas AttributeError. Fix by coercing time columns to datetime64[ns] for rendering.

Extracting data from Excel via win32com is a pragmatic choice when you already live inside the Office stack. The surprise comes when a column with time values shows up as pywintypes.datetime and a seemingly straightforward DataFrame print triggers AttributeError: 'NoneType' object has no attribute 'total_seconds'. The root of the friction is the mismatch between COM datetime objects and what pandas expects for its own datetime dtype.

Reproducing the issue

The example below automates Excel, pulls a ListObject table, converts its body range to a NumPy array, and attempts to build a pandas DataFrame. The schema includes a time column coming from Excel and another column with a None value.

import win32com.client as W32C
import numpy as np
import pandas as pd

# Launch Excel
app = W32C.gencache.EnsureDispatch('Excel.Application')
app.Visible = True

# Open workbook and locate table
book = app.Workbooks.Open('Test Excel.xlsx')
sheet = book.Worksheets('Sheet1')
listobj = sheet.ListObjects('Table1')

# Read headers
hdr = listobj.HeaderRowRange()
col_names = list(np.array(hdr))

# Read table body and convert to NumPy array
body = listobj.DataBodyRange()
body_arr = np.array(body)

# Inspect what Excel returned
for rec in body:
    print(rec)
for rec in body_arr:
    print(rec)

# Build DataFrame
df = pd.DataFrame(body_arr, columns=col_names)
print(df)

At this point, printing the DataFrame can raise the pandas traceback ending with AttributeError: 'NoneType' object has no attribute 'total_seconds'.

What’s going on

Excel delivers date/time cells through COM as pywintypes.datetime. When pandas sees these values inside a column, it treats the column as datetime-like and tries to represent it using its own datetime machinery. That conversion path includes timezone and DST handling; with pywintypes.datetime in the mix, pandas hits a branch where an expected piece of timezone metadata is None, and the render step fails.

The fix is to normalize those values into native NumPy datetime64 first. A reliable way is to round-trip through the integer representation and then cast to datetime64[ns].

The fix

If you want to handle all datetime-like columns in one pass, detect them and normalize.

from pandas.api.types import is_datetime64_any_dtype as is_dt64

for col in df.columns:
    if is_dt64(df[col]):
        df[col] = df[col].astype('int64').astype('datetime64[ns]')

If you only need to process a single time column, apply the same two-step cast to that column directly.

df['Time Column'] = df['Time Column'].astype('int64').astype('datetime64[ns]')

Why this matters

Pandas and NumPy rely on well-defined, vectorized datetime dtypes for performance and correctness. Letting foreign datetime objects slip through can break display, formatting, grouping, and any time-aware operation. Normalizing early prevents hard-to-trace runtime errors and keeps downstream analytics fast and predictable.

Conclusion

When pulling Excel tables via win32com, expect pywintypes.datetime in date columns. Before you work with the DataFrame, coerce those columns to pandas-native datetime by casting to int64 and then to datetime64[ns]. This removes the COM-specific baggage, stops the AttributeError during rendering, and restores the usual datetime semantics in pandas without per-row iteration.