[{"data":1,"prerenderedAt":1702},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Frefresh-pivot-tables-and-queries-in-excel-with-python":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Frefresh-pivot-tables-and-queries-in-excel-with-python":1693},{"id":4,"title":5,"body":6,"dateModified":1670,"datePublished":1670,"description":1671,"extension":1672,"faq":1673,"meta":1684,"navigation":204,"path":1685,"seo":1686,"slug":1689,"stem":1690,"type":1691,"__hash__":1692},"docs\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Frefresh-pivot-tables-and-queries-in-excel-with-python\u002Findex.md","Refresh Excel Pivot Tables and Queries with Python",{"type":7,"value":8,"toc":1654},"minimark",[9,19,120,125,128,156,163,167,170,383,402,406,412,556,562,566,569,722,729,849,853,856,1003,1009,1013,1023,1099,1102,1106,1109,1289,1302,1306,1309,1394,1397,1401,1404,1489,1492,1496,1545,1549,1556,1560,1566,1570,1576,1582,1600,1606,1612,1616,1650],[10,11,12,13,18],"p",{},"Some workbooks cannot be finished by a library. A file whose numbers come from pivot caches, Power Query connections or volatile formulas needs Excel's own calculation engine to produce them, and no pure-Python package computes those. When the file must arrive with fresh values, the answer is to drive a real Excel instance — with xlwings or pywin32 — refresh it, and save. This guide does that reliably, and then covers the headless alternative for the servers where Excel does not exist. It extends ",[14,15,17],"a",{"href":16},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002F","Automating Excel with xlwings Basics",".",[20,21,29,30,29,34,29,38,29,45,29,52,29,57,29,65,29,73,29,78,29,81,29,85,29,89,29,94,29,98,29,103,29,105,29,108,29,111,29,115],"svg",{"viewBox":22,"role":23,"ariaLabelledBy":24,"xmlns":27,"style":28},"0 0 760 238","img",[25,26],"rf-t","rf-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  ",[31,32,33],"title",{"id":25},"What each tool can and cannot compute",[35,36,37],"desc",{"id":26},"openpyxl reads and writes the file's stored values and definitions, while only a running Excel recalculates formulas, pivot caches and query connections.",[39,40],"rect",{"x":41,"y":41,"width":42,"height":43,"fill":44},"0","760","238","#ffffff",[46,47,51],"text",{"x":48,"y":49,"style":50},"196","28","font-size:12.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","a Python library alone",[46,53,56],{"x":54,"y":49,"style":55},"566","font-size:12.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Excel driven from Python",[58,59],"line",{"x1":60,"y1":61,"x2":60,"y2":62,"stroke":63,"style":64},"380","40","222","var(--line,#cdd5e6)","stroke-width:1px",[39,66],{"x":67,"y":68,"width":69,"height":70,"rx":71,"fill":72,"stroke":63},"30","46","332","42","9","#ebebfd",[46,74,77],{"x":48,"y":75,"style":76},"72","font-size:12px;fill:var(--text,#172033);text-anchor:middle","read and write cell values",[39,79],{"x":67,"y":80,"width":69,"height":70,"rx":71,"fill":72,"stroke":63},"96",[46,82,84],{"x":48,"y":83,"style":76},"122","preserve a pivot definition",[39,86],{"x":67,"y":87,"width":69,"height":70,"rx":71,"fill":88,"stroke":63},"146","#fee8f2",[46,90,93],{"x":48,"y":91,"style":92},"172","font-size:12px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","cannot recalculate anything",[39,95],{"x":96,"y":68,"width":69,"height":70,"rx":71,"fill":97,"stroke":63},"398","#d9f4f1",[46,99,102],{"x":100,"y":75,"style":101},"564","font-size:12px;fill:var(--teal-ink,#0b6157);text-anchor:middle","recalculates every formula",[39,104],{"x":96,"y":80,"width":69,"height":70,"rx":71,"fill":97,"stroke":63},[46,106,107],{"x":100,"y":83,"style":101},"rebuilds pivot caches",[39,109],{"x":96,"y":87,"width":69,"height":70,"rx":71,"fill":110,"stroke":63},"#fdefd8",[46,112,114],{"x":100,"y":91,"style":113},"font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","needs Excel and a desktop session",[46,116,119],{"x":60,"y":117,"style":118},"218","font-size:11.5px;fill:var(--muted,#5b6780);text-anchor:middle","Choose the left column unless the workbook genuinely needs Excel's engine",[121,122,124],"h2",{"id":123},"prerequisites","Prerequisites",[10,126,127],{},"On Windows with Excel installed:",[129,130,135],"pre",{"className":131,"code":132,"language":133,"meta":134,"style":134},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install xlwings pandas\n","bash","",[136,137,138],"code",{"__ignoreMap":134},[139,140,142,146,150,153],"span",{"class":58,"line":141},1,[139,143,145],{"class":144},"sMTad","pip",[139,147,149],{"class":148},"srMev"," install",[139,151,152],{"class":148}," xlwings",[139,154,155],{"class":148}," pandas\n",[10,157,158,159,162],{},"xlwings wraps the COM interface and works on Windows and macOS. ",[136,160,161],{},"pywin32"," is the lower-level alternative on Windows and exposes the same object model with more verbosity.",[121,164,166],{"id":165},"refresh-everything-and-save","Refresh everything and save",[10,168,169],{},"The whole job is four lines of intent — open, refresh, calculate, save — plus the care that makes it reliable:",[129,171,175],{"className":172,"code":173,"language":174,"meta":134,"style":134},"language-python shiki shiki-themes github-light github-dark-high-contrast","\"\"\"refresh.py — open a workbook, refresh it, save, quit.\"\"\"\nfrom pathlib import Path\n\nimport xlwings as xw\n\npath = Path(\"dashboard.xlsx\").resolve()\n\nwith xw.App(visible=False, add_book=False) as app:\n    app.display_alerts = False\n    app.screen_updating = False\n\n    book = app.books.open(str(path), update_links=False)\n    try:\n        book.api.RefreshAll()          # pivot caches and query connections\n        app.api.CalculateUntilAsyncQueriesDone()\n        book.save()\n    finally:\n        book.close()\n","python",[136,176,177,182,199,206,220,225,243,248,285,296,306,311,338,347,357,363,369,377],{"__ignoreMap":134},[139,178,179],{"class":58,"line":141},[139,180,181],{"class":148},"\"\"\"refresh.py — open a workbook, refresh it, save, quit.\"\"\"\n",[139,183,185,189,193,196],{"class":58,"line":184},2,[139,186,188],{"class":187},"s-kum","from",[139,190,192],{"class":191},"skGVy"," pathlib ",[139,194,195],{"class":187},"import",[139,197,198],{"class":191}," Path\n",[139,200,202],{"class":58,"line":201},3,[139,203,205],{"emptyLinePlaceholder":204},true,"\n",[139,207,209,211,214,217],{"class":58,"line":208},4,[139,210,195],{"class":187},[139,212,213],{"class":191}," xlwings ",[139,215,216],{"class":187},"as",[139,218,219],{"class":191}," xw\n",[139,221,223],{"class":58,"line":222},5,[139,224,205],{"emptyLinePlaceholder":204},[139,226,228,231,234,237,240],{"class":58,"line":227},6,[139,229,230],{"class":191},"path ",[139,232,233],{"class":187},"=",[139,235,236],{"class":191}," Path(",[139,238,239],{"class":148},"\"dashboard.xlsx\"",[139,241,242],{"class":191},").resolve()\n",[139,244,246],{"class":58,"line":245},7,[139,247,205],{"emptyLinePlaceholder":204},[139,249,251,254,257,261,263,267,270,273,275,277,280,282],{"class":58,"line":250},8,[139,252,253],{"class":187},"with",[139,255,256],{"class":191}," xw.App(",[139,258,260],{"class":259},"sa561","visible",[139,262,233],{"class":187},[139,264,266],{"class":265},"sP0c6","False",[139,268,269],{"class":191},", ",[139,271,272],{"class":259},"add_book",[139,274,233],{"class":187},[139,276,266],{"class":265},[139,278,279],{"class":191},") ",[139,281,216],{"class":187},[139,283,284],{"class":191}," app:\n",[139,286,288,291,293],{"class":58,"line":287},9,[139,289,290],{"class":191},"    app.display_alerts ",[139,292,233],{"class":187},[139,294,295],{"class":265}," False\n",[139,297,299,302,304],{"class":58,"line":298},10,[139,300,301],{"class":191},"    app.screen_updating ",[139,303,233],{"class":187},[139,305,295],{"class":265},[139,307,309],{"class":58,"line":308},11,[139,310,205],{"emptyLinePlaceholder":204},[139,312,314,317,319,322,325,328,331,333,335],{"class":58,"line":313},12,[139,315,316],{"class":191},"    book ",[139,318,233],{"class":187},[139,320,321],{"class":191}," app.books.open(",[139,323,324],{"class":265},"str",[139,326,327],{"class":191},"(path), ",[139,329,330],{"class":259},"update_links",[139,332,233],{"class":187},[139,334,266],{"class":265},[139,336,337],{"class":191},")\n",[139,339,341,344],{"class":58,"line":340},13,[139,342,343],{"class":187},"    try",[139,345,346],{"class":191},":\n",[139,348,350,353],{"class":58,"line":349},14,[139,351,352],{"class":191},"        book.api.RefreshAll()          ",[139,354,356],{"class":355},"s-wDw","# pivot caches and query connections\n",[139,358,360],{"class":58,"line":359},15,[139,361,362],{"class":191},"        app.api.CalculateUntilAsyncQueriesDone()\n",[139,364,366],{"class":58,"line":365},16,[139,367,368],{"class":191},"        book.save()\n",[139,370,372,375],{"class":58,"line":371},17,[139,373,374],{"class":187},"    finally",[139,376,346],{"class":191},[139,378,380],{"class":58,"line":379},18,[139,381,382],{"class":191},"        book.close()\n",[10,384,385,386,389,390,393,394,397,398,401],{},"Three settings prevent the classic hang. ",[136,387,388],{},"display_alerts = False"," stops a modal dialog — \"a file is already open\", \"do you want to update links\" — waiting forever for a click nobody will give it. ",[136,391,392],{},"visible=False"," keeps the window off the screen. And ",[136,395,396],{},"CalculateUntilAsyncQueriesDone()"," is what actually waits: ",[136,399,400],{},"RefreshAll"," returns immediately for anything running in the background, so saving straight after it writes the old values.",[121,403,405],{"id":404},"make-the-refresh-synchronous","Make the refresh synchronous",[10,407,408,409,411],{},"The most reliable approach is to turn background refresh off per connection, so ",[136,410,400],{}," cannot return early:",[129,413,415],{"className":172,"code":414,"language":174,"meta":134,"style":134},"import xlwings as xw\n\nwith xw.App(visible=False, add_book=False) as app:\n    app.display_alerts = False\n    book = app.books.open(\"dashboard.xlsx\")\n    try:\n        for connection in book.api.Connections:\n            try:\n                connection.OLEDBConnection.BackgroundQuery = False\n            except Exception:            # not every connection type has one\n                pass\n        book.api.RefreshAll()\n        app.api.CalculateFullRebuild()\n        book.save()\n    finally:\n        book.close()\n",[136,416,417,427,431,457,465,477,483,497,504,513,527,532,537,542,546,552],{"__ignoreMap":134},[139,418,419,421,423,425],{"class":58,"line":141},[139,420,195],{"class":187},[139,422,213],{"class":191},[139,424,216],{"class":187},[139,426,219],{"class":191},[139,428,429],{"class":58,"line":184},[139,430,205],{"emptyLinePlaceholder":204},[139,432,433,435,437,439,441,443,445,447,449,451,453,455],{"class":58,"line":201},[139,434,253],{"class":187},[139,436,256],{"class":191},[139,438,260],{"class":259},[139,440,233],{"class":187},[139,442,266],{"class":265},[139,444,269],{"class":191},[139,446,272],{"class":259},[139,448,233],{"class":187},[139,450,266],{"class":265},[139,452,279],{"class":191},[139,454,216],{"class":187},[139,456,284],{"class":191},[139,458,459,461,463],{"class":58,"line":208},[139,460,290],{"class":191},[139,462,233],{"class":187},[139,464,295],{"class":265},[139,466,467,469,471,473,475],{"class":58,"line":222},[139,468,316],{"class":191},[139,470,233],{"class":187},[139,472,321],{"class":191},[139,474,239],{"class":148},[139,476,337],{"class":191},[139,478,479,481],{"class":58,"line":227},[139,480,343],{"class":187},[139,482,346],{"class":191},[139,484,485,488,491,494],{"class":58,"line":245},[139,486,487],{"class":187},"        for",[139,489,490],{"class":191}," connection ",[139,492,493],{"class":187},"in",[139,495,496],{"class":191}," book.api.Connections:\n",[139,498,499,502],{"class":58,"line":250},[139,500,501],{"class":187},"            try",[139,503,346],{"class":191},[139,505,506,509,511],{"class":58,"line":287},[139,507,508],{"class":191},"                connection.OLEDBConnection.BackgroundQuery ",[139,510,233],{"class":187},[139,512,295],{"class":265},[139,514,515,518,521,524],{"class":58,"line":298},[139,516,517],{"class":187},"            except",[139,519,520],{"class":265}," Exception",[139,522,523],{"class":191},":            ",[139,525,526],{"class":355},"# not every connection type has one\n",[139,528,529],{"class":58,"line":308},[139,530,531],{"class":187},"                pass\n",[139,533,534],{"class":58,"line":313},[139,535,536],{"class":191},"        book.api.RefreshAll()\n",[139,538,539],{"class":58,"line":340},[139,540,541],{"class":191},"        app.api.CalculateFullRebuild()\n",[139,543,544],{"class":58,"line":349},[139,545,368],{"class":191},[139,547,548,550],{"class":58,"line":359},[139,549,374],{"class":187},[139,551,346],{"class":191},[139,553,554],{"class":58,"line":365},[139,555,382],{"class":191},[10,557,558,561],{},[136,559,560],{},"CalculateFullRebuild()"," is the heaviest recalculation Excel offers — it rebuilds the dependency tree as well as recomputing — which is what you want in an unattended job where a stale cached value would go unnoticed.",[121,563,565],{"id":564},"refresh-one-pivot-table-at-a-time","Refresh one pivot table at a time",[10,567,568],{},"When only part of the workbook needs updating, address the pivot caches directly:",[129,570,572],{"className":172,"code":571,"language":174,"meta":134,"style":134},"import xlwings as xw\n\nwith xw.App(visible=False, add_book=False) as app:\n    app.display_alerts = False\n    book = app.books.open(\"dashboard.xlsx\")\n    try:\n        for cache in book.api.PivotCaches():\n            cache.Refresh()\n\n        sheet = book.sheets[\"Summary\"]\n        for pivot in sheet.api.PivotTables():\n            print(\"refreshed:\", pivot.Name)\n            pivot.RefreshTable()\n        book.save()\n    finally:\n        book.close()\n",[136,573,574,584,588,614,622,634,640,652,657,661,677,689,703,708,712,718],{"__ignoreMap":134},[139,575,576,578,580,582],{"class":58,"line":141},[139,577,195],{"class":187},[139,579,213],{"class":191},[139,581,216],{"class":187},[139,583,219],{"class":191},[139,585,586],{"class":58,"line":184},[139,587,205],{"emptyLinePlaceholder":204},[139,589,590,592,594,596,598,600,602,604,606,608,610,612],{"class":58,"line":201},[139,591,253],{"class":187},[139,593,256],{"class":191},[139,595,260],{"class":259},[139,597,233],{"class":187},[139,599,266],{"class":265},[139,601,269],{"class":191},[139,603,272],{"class":259},[139,605,233],{"class":187},[139,607,266],{"class":265},[139,609,279],{"class":191},[139,611,216],{"class":187},[139,613,284],{"class":191},[139,615,616,618,620],{"class":58,"line":208},[139,617,290],{"class":191},[139,619,233],{"class":187},[139,621,295],{"class":265},[139,623,624,626,628,630,632],{"class":58,"line":222},[139,625,316],{"class":191},[139,627,233],{"class":187},[139,629,321],{"class":191},[139,631,239],{"class":148},[139,633,337],{"class":191},[139,635,636,638],{"class":58,"line":227},[139,637,343],{"class":187},[139,639,346],{"class":191},[139,641,642,644,647,649],{"class":58,"line":245},[139,643,487],{"class":187},[139,645,646],{"class":191}," cache ",[139,648,493],{"class":187},[139,650,651],{"class":191}," book.api.PivotCaches():\n",[139,653,654],{"class":58,"line":250},[139,655,656],{"class":191},"            cache.Refresh()\n",[139,658,659],{"class":58,"line":287},[139,660,205],{"emptyLinePlaceholder":204},[139,662,663,666,668,671,674],{"class":58,"line":298},[139,664,665],{"class":191},"        sheet ",[139,667,233],{"class":187},[139,669,670],{"class":191}," book.sheets[",[139,672,673],{"class":148},"\"Summary\"",[139,675,676],{"class":191},"]\n",[139,678,679,681,684,686],{"class":58,"line":308},[139,680,487],{"class":187},[139,682,683],{"class":191}," pivot ",[139,685,493],{"class":187},[139,687,688],{"class":191}," sheet.api.PivotTables():\n",[139,690,691,694,697,700],{"class":58,"line":313},[139,692,693],{"class":265},"            print",[139,695,696],{"class":191},"(",[139,698,699],{"class":148},"\"refreshed:\"",[139,701,702],{"class":191},", pivot.Name)\n",[139,704,705],{"class":58,"line":340},[139,706,707],{"class":191},"            pivot.RefreshTable()\n",[139,709,710],{"class":58,"line":349},[139,711,368],{"class":191},[139,713,714,716],{"class":58,"line":359},[139,715,374],{"class":187},[139,717,346],{"class":191},[139,719,720],{"class":58,"line":365},[139,721,382],{"class":191},[10,723,724,725,728],{},"Refreshing the cache updates the data behind every pivot that shares it; ",[136,726,727],{},"RefreshTable()"," re-lays out one pivot. Doing both is belt and braces, and cheap compared with opening Excel in the first place.",[20,730,29,735,29,738,29,741,29,744,29,749,29,756,29,762,29,766,29,773,29,778,29,781,29,785,29,788,29,792,29,795,29,798,29,803,29,807,29,811,29,814,29,817,29,821,29,824,29,829,29,833,29,838,29,844],{"viewBox":731,"role":23,"ariaLabelledBy":732,"xmlns":27,"style":28},"0 0 760 230",[733,734],"rf2-t","rf2-d",[31,736,737],{"id":733},"The order a reliable refresh has to follow",[35,739,740],{"id":734},"Alerts are disabled, background query is turned off, the workbook is refreshed, calculation is forced to completion, and only then is the file saved and Excel closed.",[39,742],{"x":41,"y":41,"width":42,"height":743,"fill":44},"230",[46,745,748],{"x":60,"y":746,"style":747},"26","font-size:13px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","Save too early and you ship yesterday's numbers",[39,750],{"x":751,"y":752,"width":753,"height":754,"rx":755,"fill":72,"stroke":63},"24","52","136","60","11",[46,757,761],{"x":758,"y":759,"style":760},"92","78","font-size:11.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","1. silence",[46,763,765],{"x":758,"y":764,"style":118},"98","alerts off",[58,767],{"x1":768,"y1":769,"x2":770,"y2":769,"stroke":771,"style":772},"160","82","188","var(--brand,#5b5cf0)","stroke-width:2px",[774,775],"polygon",{"points":776,"fill":777},"188,82 178,77 178,87","#5b5cf0",[39,779],{"x":780,"y":752,"width":753,"height":754,"rx":755,"fill":72,"stroke":63},"192",[46,782,784],{"x":783,"y":759,"style":760},"260","2. synchronise",[46,786,787],{"x":783,"y":764,"style":118},"background off",[58,789],{"x1":790,"y1":769,"x2":791,"y2":769,"stroke":771,"style":772},"328","356",[774,793],{"points":794,"fill":777},"356,82 346,77 346,87",[39,796],{"x":797,"y":752,"width":753,"height":754,"rx":755,"fill":110,"stroke":63},"360",[46,799,802],{"x":800,"y":759,"style":801},"428","font-size:11.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","3. RefreshAll",[46,804,806],{"x":800,"y":764,"style":805},"font-size:11.5px;fill:var(--gold-ink,#7a4e06);text-anchor:middle","caches, queries",[58,808],{"x1":809,"y1":769,"x2":810,"y2":769,"stroke":771,"style":772},"496","524",[774,812],{"points":813,"fill":777},"524,82 514,77 514,87",[39,815],{"x":816,"y":752,"width":753,"height":754,"rx":755,"fill":110,"stroke":63},"528",[46,818,820],{"x":819,"y":759,"style":801},"596","4. calculate",[46,822,823],{"x":819,"y":764,"style":805},"until done",[58,825],{"x1":819,"y1":826,"x2":819,"y2":827,"stroke":828,"style":772},"112","140","var(--teal,#0f9488)",[774,830],{"points":831,"fill":832},"596,140 591,130 601,130","#0f766e",[39,834],{"x":797,"y":835,"width":836,"height":837,"rx":755,"fill":97,"stroke":63},"144","304","56",[46,839,843],{"x":840,"y":841,"style":842},"512","170","font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","5. save, close the book, quit the app",[46,845,848],{"x":840,"y":846,"style":847},"190","font-size:11.5px;fill:var(--teal-ink,#0b6157);text-anchor:middle","in a finally block, always",[121,850,852],{"id":851},"the-pywin32-equivalent","The pywin32 equivalent",[10,854,855],{},"If you would rather not add xlwings, the same operations are available directly through COM:",[129,857,859],{"className":172,"code":858,"language":174,"meta":134,"style":134},"import win32com.client as win32\n\nexcel = win32.DispatchEx(\"Excel.Application\")\nexcel.Visible = False\nexcel.DisplayAlerts = False\ntry:\n    book = excel.Workbooks.Open(r\"C:\\reports\\dashboard.xlsx\", UpdateLinks=0)\n    book.RefreshAll()\n    excel.CalculateUntilAsyncQueriesDone()\n    book.Save()\n    book.Close(SaveChanges=True)\nfinally:\n    excel.Quit()\n",[136,860,861,873,877,892,901,910,917,961,966,971,976,991,998],{"__ignoreMap":134},[139,862,863,865,868,870],{"class":58,"line":141},[139,864,195],{"class":187},[139,866,867],{"class":191}," win32com.client ",[139,869,216],{"class":187},[139,871,872],{"class":191}," win32\n",[139,874,875],{"class":58,"line":184},[139,876,205],{"emptyLinePlaceholder":204},[139,878,879,882,884,887,890],{"class":58,"line":201},[139,880,881],{"class":191},"excel ",[139,883,233],{"class":187},[139,885,886],{"class":191}," win32.DispatchEx(",[139,888,889],{"class":148},"\"Excel.Application\"",[139,891,337],{"class":191},[139,893,894,897,899],{"class":58,"line":208},[139,895,896],{"class":191},"excel.Visible ",[139,898,233],{"class":187},[139,900,295],{"class":265},[139,902,903,906,908],{"class":58,"line":222},[139,904,905],{"class":191},"excel.DisplayAlerts ",[139,907,233],{"class":187},[139,909,295],{"class":265},[139,911,912,915],{"class":58,"line":227},[139,913,914],{"class":187},"try",[139,916,346],{"class":191},[139,918,919,921,923,926,929,932,936,939,942,945,947,950,952,955,957,959],{"class":58,"line":245},[139,920,316],{"class":191},[139,922,233],{"class":187},[139,924,925],{"class":191}," excel.Workbooks.Open(",[139,927,928],{"class":187},"r",[139,930,931],{"class":148},"\"C:",[139,933,935],{"class":934},"s_b0D","\\r",[139,937,938],{"class":148},"eports",[139,940,941],{"class":265},"\\d",[139,943,944],{"class":148},"ashboard",[139,946,18],{"class":265},[139,948,949],{"class":148},"xlsx\"",[139,951,269],{"class":191},[139,953,954],{"class":259},"UpdateLinks",[139,956,233],{"class":187},[139,958,41],{"class":265},[139,960,337],{"class":191},[139,962,963],{"class":58,"line":250},[139,964,965],{"class":191},"    book.RefreshAll()\n",[139,967,968],{"class":58,"line":287},[139,969,970],{"class":191},"    excel.CalculateUntilAsyncQueriesDone()\n",[139,972,973],{"class":58,"line":298},[139,974,975],{"class":191},"    book.Save()\n",[139,977,978,981,984,986,989],{"class":58,"line":308},[139,979,980],{"class":191},"    book.Close(",[139,982,983],{"class":259},"SaveChanges",[139,985,233],{"class":187},[139,987,988],{"class":265},"True",[139,990,337],{"class":191},[139,992,993,996],{"class":58,"line":313},[139,994,995],{"class":187},"finally",[139,997,346],{"class":191},[139,999,1000],{"class":58,"line":340},[139,1001,1002],{"class":191},"    excel.Quit()\n",[10,1004,1005,1008],{},[136,1006,1007],{},"DispatchEx"," starts a fresh Excel process rather than attaching to one the user already has open — important in automation, where attaching to a colleague's session means their unsaved work and their modal dialogs become your problem.",[121,1010,1012],{"id":1011},"clean-up-or-accumulate-orphan-processes","Clean up, or accumulate orphan processes",[10,1014,1015,1016,1019,1020,1022],{},"The most common operational failure of Excel automation is a pile of invisible ",[136,1017,1018],{},"EXCEL.EXE"," processes, each holding a file lock. Two habits prevent it: always quit in a ",[136,1021,995],{}," block, and sweep before you start:",[129,1024,1026],{"className":172,"code":1025,"language":174,"meta":134,"style":134},"\"\"\"Kill orphaned Excel processes left by earlier failures.\"\"\"\nimport psutil\n\nfor proc in psutil.process_iter([\"name\"]):\n    if proc.info[\"name\"] and proc.info[\"name\"].lower() == \"excel.exe\":\n        proc.kill()\n",[136,1027,1028,1033,1040,1044,1063,1094],{"__ignoreMap":134},[139,1029,1030],{"class":58,"line":141},[139,1031,1032],{"class":148},"\"\"\"Kill orphaned Excel processes left by earlier failures.\"\"\"\n",[139,1034,1035,1037],{"class":58,"line":184},[139,1036,195],{"class":187},[139,1038,1039],{"class":191}," psutil\n",[139,1041,1042],{"class":58,"line":201},[139,1043,205],{"emptyLinePlaceholder":204},[139,1045,1046,1049,1052,1054,1057,1060],{"class":58,"line":208},[139,1047,1048],{"class":187},"for",[139,1050,1051],{"class":191}," proc ",[139,1053,493],{"class":187},[139,1055,1056],{"class":191}," psutil.process_iter([",[139,1058,1059],{"class":148},"\"name\"",[139,1061,1062],{"class":191},"]):\n",[139,1064,1065,1068,1071,1073,1076,1079,1081,1083,1086,1089,1092],{"class":58,"line":222},[139,1066,1067],{"class":187},"    if",[139,1069,1070],{"class":191}," proc.info[",[139,1072,1059],{"class":148},[139,1074,1075],{"class":191},"] ",[139,1077,1078],{"class":187},"and",[139,1080,1070],{"class":191},[139,1082,1059],{"class":148},[139,1084,1085],{"class":191},"].lower() ",[139,1087,1088],{"class":187},"==",[139,1090,1091],{"class":148}," \"excel.exe\"",[139,1093,346],{"class":191},[139,1095,1096],{"class":58,"line":227},[139,1097,1098],{"class":191},"        proc.kill()\n",[10,1100,1101],{},"Only do that on a dedicated automation machine — killing Excel on a shared desktop destroys someone's unsaved work. On a machine where a person also works, prefer detecting the orphan and failing loudly.",[121,1103,1105],{"id":1104},"the-headless-alternative","The headless alternative",[10,1107,1108],{},"If the workbook exists to present an aggregation, compute the aggregation in Python and write the values. Then nothing needs refreshing, and the report runs on any server:",[129,1110,1112],{"className":172,"code":1111,"language":174,"meta":134,"style":134},"import pandas as pd\n\ndf = pd.read_excel(\"raw_data.xlsx\", engine=\"calamine\")\nsummary = (df.groupby([\"region\", \"product\"], as_index=False)[\"revenue\"]\n             .sum()\n             .sort_values(\"revenue\", ascending=False))\n\nwith pd.ExcelWriter(\"dashboard.xlsx\", engine=\"xlsxwriter\") as writer:\n    summary.to_excel(writer, index=False, sheet_name=\"Summary\")\n    df.to_excel(writer, index=False, sheet_name=\"Data\")\n",[136,1113,1114,1126,1130,1155,1191,1196,1215,1219,1244,1267],{"__ignoreMap":134},[139,1115,1116,1118,1121,1123],{"class":58,"line":141},[139,1117,195],{"class":187},[139,1119,1120],{"class":191}," pandas ",[139,1122,216],{"class":187},[139,1124,1125],{"class":191}," pd\n",[139,1127,1128],{"class":58,"line":184},[139,1129,205],{"emptyLinePlaceholder":204},[139,1131,1132,1135,1137,1140,1143,1145,1148,1150,1153],{"class":58,"line":201},[139,1133,1134],{"class":191},"df ",[139,1136,233],{"class":187},[139,1138,1139],{"class":191}," pd.read_excel(",[139,1141,1142],{"class":148},"\"raw_data.xlsx\"",[139,1144,269],{"class":191},[139,1146,1147],{"class":259},"engine",[139,1149,233],{"class":187},[139,1151,1152],{"class":148},"\"calamine\"",[139,1154,337],{"class":191},[139,1156,1157,1160,1162,1165,1168,1170,1173,1176,1179,1181,1183,1186,1189],{"class":58,"line":208},[139,1158,1159],{"class":191},"summary ",[139,1161,233],{"class":187},[139,1163,1164],{"class":191}," (df.groupby([",[139,1166,1167],{"class":148},"\"region\"",[139,1169,269],{"class":191},[139,1171,1172],{"class":148},"\"product\"",[139,1174,1175],{"class":191},"], ",[139,1177,1178],{"class":259},"as_index",[139,1180,233],{"class":187},[139,1182,266],{"class":265},[139,1184,1185],{"class":191},")[",[139,1187,1188],{"class":148},"\"revenue\"",[139,1190,676],{"class":191},[139,1192,1193],{"class":58,"line":222},[139,1194,1195],{"class":191},"             .sum()\n",[139,1197,1198,1201,1203,1205,1208,1210,1212],{"class":58,"line":227},[139,1199,1200],{"class":191},"             .sort_values(",[139,1202,1188],{"class":148},[139,1204,269],{"class":191},[139,1206,1207],{"class":259},"ascending",[139,1209,233],{"class":187},[139,1211,266],{"class":265},[139,1213,1214],{"class":191},"))\n",[139,1216,1217],{"class":58,"line":245},[139,1218,205],{"emptyLinePlaceholder":204},[139,1220,1221,1223,1226,1228,1230,1232,1234,1237,1239,1241],{"class":58,"line":250},[139,1222,253],{"class":187},[139,1224,1225],{"class":191}," pd.ExcelWriter(",[139,1227,239],{"class":148},[139,1229,269],{"class":191},[139,1231,1147],{"class":259},[139,1233,233],{"class":187},[139,1235,1236],{"class":148},"\"xlsxwriter\"",[139,1238,279],{"class":191},[139,1240,216],{"class":187},[139,1242,1243],{"class":191}," writer:\n",[139,1245,1246,1249,1252,1254,1256,1258,1261,1263,1265],{"class":58,"line":287},[139,1247,1248],{"class":191},"    summary.to_excel(writer, ",[139,1250,1251],{"class":259},"index",[139,1253,233],{"class":187},[139,1255,266],{"class":265},[139,1257,269],{"class":191},[139,1259,1260],{"class":259},"sheet_name",[139,1262,233],{"class":187},[139,1264,673],{"class":148},[139,1266,337],{"class":191},[139,1268,1269,1272,1274,1276,1278,1280,1282,1284,1287],{"class":58,"line":298},[139,1270,1271],{"class":191},"    df.to_excel(writer, ",[139,1273,1251],{"class":259},[139,1275,233],{"class":187},[139,1277,266],{"class":265},[139,1279,269],{"class":191},[139,1281,1260],{"class":259},[139,1283,233],{"class":187},[139,1285,1286],{"class":148},"\"Data\"",[139,1288,337],{"class":191},[10,1290,1291,1292,1296,1297,1301],{},"This is the right default. A pivot table is a presentation of a group-by; if the group-by happens in pandas, the workbook holds finished numbers that open correctly everywhere — no Excel licence, no desktop session, no COM. The techniques are in ",[14,1293,1295],{"href":1294},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fcreate-pivot-table-from-excel-with-pandas\u002F","Create a pivot table from Excel with pandas",", and if a genuine Excel pivot object is required, ",[14,1298,1300],{"href":1299},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fadd-a-native-excel-pivot-table-with-python\u002F","Add a native Excel pivot table with Python"," shows how to define one that refreshes on open.",[121,1303,1305],{"id":1304},"make-a-workbook-refresh-itself-when-opened","Make a workbook refresh itself when opened",[10,1307,1308],{},"Between the two extremes there is a middle path: mark the pivot cache to refresh when the file is opened, so the recipient's own Excel does the work:",[129,1310,1312],{"className":172,"code":1311,"language":174,"meta":134,"style":134},"from openpyxl import load_workbook\n\nwb = load_workbook(\"dashboard.xlsx\")\nfor cache in wb._pivots if hasattr(wb, \"_pivots\") else []:\n    cache.cache.refreshOnLoad = True\nwb.save(\"dashboard.xlsx\")\n",[136,1313,1314,1326,1330,1344,1375,1385],{"__ignoreMap":134},[139,1315,1316,1318,1321,1323],{"class":58,"line":141},[139,1317,188],{"class":187},[139,1319,1320],{"class":191}," openpyxl ",[139,1322,195],{"class":187},[139,1324,1325],{"class":191}," load_workbook\n",[139,1327,1328],{"class":58,"line":184},[139,1329,205],{"emptyLinePlaceholder":204},[139,1331,1332,1335,1337,1340,1342],{"class":58,"line":201},[139,1333,1334],{"class":191},"wb ",[139,1336,233],{"class":187},[139,1338,1339],{"class":191}," load_workbook(",[139,1341,239],{"class":148},[139,1343,337],{"class":191},[139,1345,1346,1348,1350,1352,1355,1358,1361,1364,1367,1369,1372],{"class":58,"line":208},[139,1347,1048],{"class":187},[139,1349,646],{"class":191},[139,1351,493],{"class":187},[139,1353,1354],{"class":191}," wb._pivots ",[139,1356,1357],{"class":187},"if",[139,1359,1360],{"class":265}," hasattr",[139,1362,1363],{"class":191},"(wb, ",[139,1365,1366],{"class":148},"\"_pivots\"",[139,1368,279],{"class":191},[139,1370,1371],{"class":187},"else",[139,1373,1374],{"class":191}," []:\n",[139,1376,1377,1380,1382],{"class":58,"line":222},[139,1378,1379],{"class":191},"    cache.cache.refreshOnLoad ",[139,1381,233],{"class":187},[139,1383,1384],{"class":265}," True\n",[139,1386,1387,1390,1392],{"class":58,"line":227},[139,1388,1389],{"class":191},"wb.save(",[139,1391,239],{"class":148},[139,1393,337],{"class":191},[10,1395,1396],{},"The values in the file are still stale, but they update the moment a person opens it. That is often enough for a distributed report, and it costs no server-side Excel at all.",[121,1398,1400],{"id":1399},"decide-which-route-your-workbook-needs","Decide which route your workbook needs",[10,1402,1403],{},"Three approaches, and the choice is made by what the file actually contains rather than by preference:",[20,1405,29,1410,29,1413,29,1416,29,1419,29,1422,29,1426,29,1432,29,1437,29,1441,29,1445,29,1449,29,1452,29,1456,29,1459,29,1462,29,1465,29,1469,29,1473,29,1477,29,1480,29,1483,29,1486],{"viewBox":1406,"role":23,"ariaLabelledBy":1407,"xmlns":27,"style":28},"0 0 760 228",[1408,1409],"rf3-t","rf3-d",[31,1411,1412],{"id":1408},"Choosing between driving Excel, refreshing on open, and computing headlessly",[35,1414,1415],{"id":1409},"Driving Excel gives fresh values but needs a licensed desktop, refresh-on-open pushes the work to the reader, and computing in pandas removes the need to refresh at all.",[39,1417],{"x":41,"y":41,"width":42,"height":1418,"fill":44},"228",[46,1420,1421],{"x":60,"y":746,"style":747},"What the workbook contains decides the route",[39,1423],{"x":49,"y":68,"width":1424,"height":87,"rx":1425,"fill":110,"stroke":63},"226","12",[46,1427,1431],{"x":1428,"y":1429,"style":1430},"141","76","font-size:12.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","drive Excel",[46,1433,1436],{"x":1428,"y":1434,"style":1435},"104","font-size:11.5px;fill:var(--text,#172033);text-anchor:middle","values fresh on delivery",[46,1438,1440],{"x":1428,"y":1439,"style":118},"128","needs Excel + a session",[46,1442,1444],{"x":1428,"y":1443,"style":118},"152","slow, serialised",[46,1446,1448],{"x":1428,"y":1447,"style":805},"176","for: legacy dashboards",[39,1450],{"x":1451,"y":68,"width":1424,"height":87,"rx":1425,"fill":72,"stroke":63},"268",[46,1453,1455],{"x":1454,"y":1429,"style":50},"381","refresh on open",[46,1457,1458],{"x":1454,"y":1434,"style":1435},"reader's Excel does it",[46,1460,1461],{"x":1454,"y":1439,"style":118},"stale until opened",[46,1463,1464],{"x":1454,"y":1443,"style":118},"no server-side Excel",[46,1466,1468],{"x":1454,"y":1447,"style":1467},"font-size:11.5px;fill:var(--brand-strong,#4338ca);text-anchor:middle","for: distributed files",[39,1470],{"x":1471,"y":68,"width":1472,"height":87,"rx":1425,"fill":97,"stroke":63},"508","224",[46,1474,1476],{"x":1475,"y":1429,"style":55},"620","compute in pandas",[46,1478,1479],{"x":1475,"y":1434,"style":1435},"values written directly",[46,1481,1482],{"x":1475,"y":1439,"style":847},"runs anywhere, fast",[46,1484,1485],{"x":1475,"y":1443,"style":118},"rebuilds the logic once",[46,1487,1488],{"x":1475,"y":1447,"style":847},"for: everything new",[10,1490,1491],{},"If you are inheriting a workbook somebody built by hand, driving Excel buys time while you port the logic. If you are building something new, port the logic first — the automation you do not have to operate is always the cheapest one.",[121,1493,1495],{"id":1494},"common-pitfalls-and-gotchas","Common pitfalls and gotchas",[1497,1498,1499,1510,1524,1530,1536],"ul",{},[1500,1501,1502,1506,1507,1509],"li",{},[1503,1504,1505],"strong",{},"Saving before the refresh completes."," ",[136,1508,400],{}," is asynchronous for background queries; wait explicitly.",[1500,1511,1512,1515,1516,1519,1520,1523],{},[1503,1513,1514],{},"A modal dialog with nobody to click it."," Set ",[136,1517,1518],{},"DisplayAlerts = False"," and ",[136,1521,1522],{},"UpdateLinks=0"," on open.",[1500,1525,1526,1529],{},[1503,1527,1528],{},"Running under a service account with no desktop."," Excel COM needs an interactive session; a scheduled task set to \"run whether user is logged on or not\" usually fails silently.",[1500,1531,1532,1535],{},[1503,1533,1534],{},"Relative paths."," COM resolves paths against Excel's working directory, not your script's. Always pass an absolute path.",[1500,1537,1538,1541,1542,1544],{},[1503,1539,1540],{},"Leaving Excel running."," Quit in a ",[136,1543,995],{},", and check the process list after a failed run.",[121,1546,1548],{"id":1547},"performance-and-scale-notes","Performance and scale notes",[10,1550,1551,1552,18],{},"Starting Excel costs seconds, not milliseconds, and a full rebuild of a large workbook can take minutes. That makes this a batch operation, never a request-time one: refresh on a schedule and serve the resulting file, rather than refreshing when someone asks. Excel is also single-instance-per-session in practice, so refreshes serialise — one machine cannot process ten workbooks in parallel the way a pandas job can. If throughput matters, the headless route is not just more portable but genuinely faster, because it skips the application entirely. Scheduling either approach is covered in ",[14,1553,1555],{"href":1554},"\u002Fautomating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Frun-python-excel-script-on-windows-task-scheduler\u002F","Run a Python Excel script on Windows Task Scheduler",[121,1557,1559],{"id":1558},"conclusion","Conclusion",[10,1561,1562,1563,1565],{},"Only Excel can recalculate Excel. When a workbook depends on pivot caches, query connections or volatile formulas, drive a hidden instance with xlwings or pywin32: silence the alerts, make the refresh synchronous, force a full calculation, save, and quit in a ",[136,1564,995],{},". But treat that as the exception — computing the aggregation in pandas and writing finished values produces a workbook that needs no refresh, runs on any server, and finishes in a fraction of the time.",[121,1567,1569],{"id":1568},"frequently-asked-questions","Frequently asked questions",[10,1571,1572,1575],{},[1503,1573,1574],{},"Can openpyxl refresh a pivot table?","\nNo. openpyxl can preserve a pivot table's definition and set it to refresh when the file is opened, but it cannot recalculate the cache — only Excel itself computes pivot results and formula values.",[10,1577,1578,1581],{},[1503,1579,1580],{},"Do I need Excel installed?","\nFor a genuine refresh, yes. xlwings and pywin32 both drive a real Excel application through COM, which means Windows (or macOS for xlwings) with Excel present. On Linux there is no Excel to drive.",[10,1583,1584,1587,1589,1590,1593,1594,1596,1597,1599],{},[1503,1585,1586],{},"How do I know when RefreshAll has finished?",[136,1588,400],{}," returns immediately for background queries. Set each connection's ",[136,1591,1592],{},"BackgroundQuery"," to ",[136,1595,266],{}," before refreshing, or call ",[136,1598,396],{},", then save.",[10,1601,1602,1605],{},[1503,1603,1604],{},"What is the headless alternative?","\nCompute the aggregation in pandas and write the values, so no recalculation is needed. A summary built from data rather than from a cache opens correctly anywhere, including on a Linux server.",[10,1607,1608,1611],{},[1503,1609,1610],{},"Why does my scheduled task do nothing when nobody is logged in?","\nExcel automation needs an interactive desktop session. A task set to run whether or not the user is logged on typically fails silently — this is the strongest argument for the headless approach.",[121,1613,1615],{"id":1614},"related","Related",[1497,1617,1618,1626,1633,1640,1645],{},[1500,1619,1620,1506,1623,1625],{},[1503,1621,1622],{},"Up:",[14,1624,17],{"href":16}," — the wider set of things a live Excel session makes possible.",[1500,1627,1628,1632],{},[14,1629,1631],{"href":1630},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fread-and-write-a-live-excel-workbook-with-xlwings\u002F","Read and write a live Excel workbook with xlwings"," — driving an open workbook rather than a saved file.",[1500,1634,1635,1639],{},[14,1636,1638],{"href":1637},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fxlwings-run-macro-from-python-example\u002F","xlwings run macro from Python example"," — the other reason to need a real Excel instance.",[1500,1641,1642,1644],{},[14,1643,1300],{"href":1299}," — creating the pivot this page refreshes.",[1500,1646,1647,1649],{},[14,1648,1295],{"href":1294}," — the headless equivalent that never needs refreshing.",[1651,1652,1653],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}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 .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}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 pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}html pre.shiki code .s_b0D, html code.shiki .s_b0D{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#72F088;--shiki-dark-font-weight:bold}",{"title":134,"searchDepth":184,"depth":184,"links":1655},[1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669],{"id":123,"depth":184,"text":124},{"id":165,"depth":184,"text":166},{"id":404,"depth":184,"text":405},{"id":564,"depth":184,"text":565},{"id":851,"depth":184,"text":852},{"id":1011,"depth":184,"text":1012},{"id":1104,"depth":184,"text":1105},{"id":1304,"depth":184,"text":1305},{"id":1399,"depth":184,"text":1400},{"id":1494,"depth":184,"text":1495},{"id":1547,"depth":184,"text":1548},{"id":1558,"depth":184,"text":1559},{"id":1568,"depth":184,"text":1569},{"id":1614,"depth":184,"text":1615},"2026-08-27","Recalculate a workbook, refresh pivot caches and Power Query connections, and save the result — with xlwings or pywin32 on Windows, plus the headless alternatives.","md",[1674,1676,1678,1680,1682],{"q":1574,"a":1675},"No. openpyxl can preserve a pivot table's definition and set it to refresh when the file is opened, but it cannot recalculate the cache — only Excel itself computes pivot results and formula values.",{"q":1580,"a":1677},"For a genuine refresh, yes. xlwings and pywin32 both drive a real Excel application through COM, which means Windows (or macOS for xlwings) with Excel present. On Linux there is no Excel to drive.",{"q":1586,"a":1679},"RefreshAll returns immediately for background queries. Set each connection's BackgroundQuery to False before refreshing, or poll CalculationState until it reports done, then save.",{"q":1604,"a":1681},"Compute the aggregation in pandas and write the values, so no recalculation is needed. A pivot table built from data rather than from a cache opens correctly anywhere, including on a Linux server.",{"q":1610,"a":1683},"Excel automation needs an interactive desktop session. A task set to run whether or not the user is logged on typically fails silently — this is the strongest argument for the headless approach.",{},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Frefresh-pivot-tables-and-queries-in-excel-with-python",{"title":1687,"description":1688},"Refresh Excel Pivot Tables from Python","Drive Excel from Python to refresh pivot tables, Power Query connections and formulas: RefreshAll, wait for completion, save, and what to do on a headless server.","refresh-pivot-tables-and-queries-in-excel-with-python","getting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Frefresh-pivot-tables-and-queries-in-excel-with-python\u002Findex","how-to","3Cx9v3SLGibwAp7z29lIEGeUaq-97Km6-OgxOGvj_TM",[1694,1698],{"title":1695,"path":1696,"stem":1697,"children":-1},"Read and Write a Live Excel Workbook with xlwings","\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fread-and-write-a-live-excel-workbook-with-xlwings","getting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fread-and-write-a-live-excel-workbook-with-xlwings\u002Findex",{"title":1699,"path":1700,"stem":1701,"children":-1},"xlwings: Run a VBA Macro From Python (Example)","\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fxlwings-run-macro-from-python-example","getting-started-with-python-excel-automation\u002Fautomating-excel-with-xlwings-basics\u002Fxlwings-run-macro-from-python-example\u002Findex",1788710163264]