[{"data":1,"prerenderedAt":1549},["ShallowReactive",2],{"doc:\u002Fautomating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Frun-python-excel-script-on-windows-task-scheduler":3,"surround:\u002Fautomating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Frun-python-excel-script-on-windows-task-scheduler":1542},{"id":4,"title":5,"body":6,"description":1533,"extension":1534,"meta":1535,"navigation":163,"path":1536,"seo":1537,"stem":1540,"__hash__":1541},"docs\u002Fautomating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Frun-python-excel-script-on-windows-task-scheduler\u002Findex.md","Run a Python Excel Script on Windows Task Scheduler",{"type":7,"value":8,"toc":1518},"minimark",[9,37,42,52,75,82,86,100,723,726,735,739,759,784,795,799,810,813,828,831,845,848,862,868,873,887,906,915,919,1112,1116,1158,1162,1165,1174,1179,1247,1250,1259,1270,1274,1376,1394,1398,1408,1425,1447,1457,1461,1492,1496,1514],[10,11,12,13,17,18,22,23,26,27,32,33,36],"p",{},"Windows has no ",[14,15,16],"code",{},"cron",", so the unattended scheduling you'd do on Linux happens through ",[19,20,21],"strong",{},"Task Scheduler"," instead. This page registers a Python report script to run on a fixed schedule using ",[14,24,25],{},"schtasks",", the command-line interface to Task Scheduler, so you can version the command and recreate the task on any machine. It is the Windows companion to ",[28,29,31],"a",{"href":30},"\u002Fautomating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002F","Scheduling Python Excel Scripts with Cron","; the report logic is identical, only the trigger mechanism changes. By the end you'll have a task that runs whether or not anyone is logged on, writes ",[14,34,35],{},"daily_summary.xlsx",", and logs every run.",[38,39,41],"h2",{"id":40},"prerequisites","Prerequisites",[43,44,45,49],"ul",{},[46,47,48],"li",{},"Windows 10\u002F11 or Windows Server with administrator access (needed to run a task while logged off).",[46,50,51],{},"Python installed with a virtualenv. Create one and install the report dependencies:",[53,54,59],"pre",{"className":55,"code":56,"language":57,"meta":58,"style":58},"language-bat shiki shiki-themes github-light github-dark","python -m venv C:\\reporting\\venv\nC:\\reporting\\venv\\Scripts\\pip install pandas openpyxl\n","bat","",[14,60,61,69],{"__ignoreMap":58},[62,63,66],"span",{"class":64,"line":65},"line",1,[62,67,68],{},"python -m venv C:\\reporting\\venv\n",[62,70,72],{"class":64,"line":71},2,[62,73,74],{},"C:\\reporting\\venv\\Scripts\\pip install pandas openpyxl\n",[10,76,77,78,81],{},"Note the absolute path ",[14,79,80],{},"C:\\reporting\\venv\\Scripts\\python.exe",". Task Scheduler does not activate virtualenvs, so you call that interpreter directly — exactly as you'd call the venv Python by absolute path under cron.",[38,83,85],{"id":84},"a-self-contained-report-script","A self-contained report script",[10,87,88,89,92,93,95,96,99],{},"Save this as ",[14,90,91],{},"C:\\reporting\\generate_daily_report.py",". It uses absolute paths, seeds sample data if none exists, writes ",[14,94,35],{},", and exits non-zero on failure so the task's ",[19,97,98],{},"Last Run Result"," reflects an error:",[53,101,105],{"className":102,"code":103,"language":104,"meta":58,"style":58},"language-python shiki shiki-themes github-light github-dark","\"\"\"Scheduled Excel report: build data, summarize, write daily_summary.xlsx.\"\"\"\nimport sys\nimport logging\nfrom datetime import datetime\nfrom pathlib import Path\n\nimport pandas as pd\n\n# Absolute paths: Task Scheduler's working directory is C:\\Windows\\System32.\nBASE_DIR = Path(r\"C:\\reporting\")\nOUTPUT_DIR = BASE_DIR \u002F \"output\"\nLOG_DIR = BASE_DIR \u002F \"logs\"\nfor d in (OUTPUT_DIR, LOG_DIR):\n    d.mkdir(parents=True, exist_ok=True)\n\nlogging.basicConfig(\n    filename=LOG_DIR \u002F f\"report_{datetime.now():%Y%m%d}.log\",\n    level=logging.INFO,\n    format=\"%(asctime)s | %(levelname)s | %(message)s\",\n)\n\ndef main():\n    logging.info(\"Starting daily Excel report.\")\n    try:\n        # Build sample data so the run is self-contained.\n        df = pd.DataFrame({\n            \"region\": [\"North\", \"South\", \"North\", \"East\", \"South\"],\n            \"revenue\": [1200.0, 980.5, 1450.0, 610.25, 980.5],\n        })\n        summary = df.groupby(\"region\", as_index=False)[\"revenue\"].sum()\n\n        out = OUTPUT_DIR \u002F \"daily_summary.xlsx\"\n        summary.to_excel(out, index=False, engine=\"openpyxl\")\n        logging.info(\"Wrote %d rows to %s\", len(summary), out)\n    except Exception:\n        logging.exception(\"Report generation failed.\")\n        sys.exit(1)\n    logging.info(\"Done.\")\n\nif __name__ == \"__main__\":\n    main()\n","python",[14,106,107,113,123,131,145,158,165,179,184,191,226,243,258,283,310,315,321,370,386,414,419,424,437,448,457,463,474,507,539,545,578,583,599,624,652,663,674,685,695,700,717],{"__ignoreMap":58},[62,108,109],{"class":64,"line":65},[62,110,112],{"class":111},"sZZnC","\"\"\"Scheduled Excel report: build data, summarize, write daily_summary.xlsx.\"\"\"\n",[62,114,115,119],{"class":64,"line":71},[62,116,118],{"class":117},"szBVR","import",[62,120,122],{"class":121},"sVt8B"," sys\n",[62,124,126,128],{"class":64,"line":125},3,[62,127,118],{"class":117},[62,129,130],{"class":121}," logging\n",[62,132,134,137,140,142],{"class":64,"line":133},4,[62,135,136],{"class":117},"from",[62,138,139],{"class":121}," datetime ",[62,141,118],{"class":117},[62,143,144],{"class":121}," datetime\n",[62,146,148,150,153,155],{"class":64,"line":147},5,[62,149,136],{"class":117},[62,151,152],{"class":121}," pathlib ",[62,154,118],{"class":117},[62,156,157],{"class":121}," Path\n",[62,159,161],{"class":64,"line":160},6,[62,162,164],{"emptyLinePlaceholder":163},true,"\n",[62,166,168,170,173,176],{"class":64,"line":167},7,[62,169,118],{"class":117},[62,171,172],{"class":121}," pandas ",[62,174,175],{"class":117},"as",[62,177,178],{"class":121}," pd\n",[62,180,182],{"class":64,"line":181},8,[62,183,164],{"emptyLinePlaceholder":163},[62,185,187],{"class":64,"line":186},9,[62,188,190],{"class":189},"sJ8bj","# Absolute paths: Task Scheduler's working directory is C:\\Windows\\System32.\n",[62,192,194,198,201,204,207,210,214,218,221,223],{"class":64,"line":193},10,[62,195,197],{"class":196},"sj4cs","BASE_DIR",[62,199,200],{"class":117}," =",[62,202,203],{"class":121}," Path(",[62,205,206],{"class":117},"r",[62,208,209],{"class":111},"\"",[62,211,213],{"class":212},"sA_wV","C:",[62,215,217],{"class":216},"snhLl","\\r",[62,219,220],{"class":212},"eporting",[62,222,209],{"class":111},[62,224,225],{"class":121},")\n",[62,227,229,232,234,237,240],{"class":64,"line":228},11,[62,230,231],{"class":196},"OUTPUT_DIR",[62,233,200],{"class":117},[62,235,236],{"class":196}," BASE_DIR",[62,238,239],{"class":117}," \u002F",[62,241,242],{"class":111}," \"output\"\n",[62,244,246,249,251,253,255],{"class":64,"line":245},12,[62,247,248],{"class":196},"LOG_DIR",[62,250,200],{"class":117},[62,252,236],{"class":196},[62,254,239],{"class":117},[62,256,257],{"class":111}," \"logs\"\n",[62,259,261,264,267,270,273,275,278,280],{"class":64,"line":260},13,[62,262,263],{"class":117},"for",[62,265,266],{"class":121}," d ",[62,268,269],{"class":117},"in",[62,271,272],{"class":121}," (",[62,274,231],{"class":196},[62,276,277],{"class":121},", ",[62,279,248],{"class":196},[62,281,282],{"class":121},"):\n",[62,284,286,289,293,296,299,301,304,306,308],{"class":64,"line":285},14,[62,287,288],{"class":121},"    d.mkdir(",[62,290,292],{"class":291},"s4XuR","parents",[62,294,295],{"class":117},"=",[62,297,298],{"class":196},"True",[62,300,277],{"class":121},[62,302,303],{"class":291},"exist_ok",[62,305,295],{"class":117},[62,307,298],{"class":196},[62,309,225],{"class":121},[62,311,313],{"class":64,"line":312},15,[62,314,164],{"emptyLinePlaceholder":163},[62,316,318],{"class":64,"line":317},16,[62,319,320],{"class":121},"logging.basicConfig(\n",[62,322,324,327,329,331,333,336,339,342,345,348,351,353,356,358,361,364,367],{"class":64,"line":323},17,[62,325,326],{"class":291},"    filename",[62,328,295],{"class":117},[62,330,248],{"class":196},[62,332,239],{"class":117},[62,334,335],{"class":117}," f",[62,337,338],{"class":111},"\"report_",[62,340,341],{"class":196},"{",[62,343,344],{"class":121},"datetime.now():",[62,346,347],{"class":117},"%",[62,349,350],{"class":121},"Y",[62,352,347],{"class":117},[62,354,355],{"class":121},"m",[62,357,347],{"class":117},[62,359,360],{"class":121},"d",[62,362,363],{"class":196},"}",[62,365,366],{"class":111},".log\"",[62,368,369],{"class":121},",\n",[62,371,373,376,378,381,384],{"class":64,"line":372},18,[62,374,375],{"class":291},"    level",[62,377,295],{"class":117},[62,379,380],{"class":121},"logging.",[62,382,383],{"class":196},"INFO",[62,385,369],{"class":121},[62,387,389,392,394,396,399,402,405,407,410,412],{"class":64,"line":388},19,[62,390,391],{"class":291},"    format",[62,393,295],{"class":117},[62,395,209],{"class":111},[62,397,398],{"class":196},"%(asctime)s",[62,400,401],{"class":111}," | ",[62,403,404],{"class":196},"%(levelname)s",[62,406,401],{"class":111},[62,408,409],{"class":196},"%(message)s",[62,411,209],{"class":111},[62,413,369],{"class":121},[62,415,417],{"class":64,"line":416},20,[62,418,225],{"class":121},[62,420,422],{"class":64,"line":421},21,[62,423,164],{"emptyLinePlaceholder":163},[62,425,427,430,434],{"class":64,"line":426},22,[62,428,429],{"class":117},"def",[62,431,433],{"class":432},"sScJk"," main",[62,435,436],{"class":121},"():\n",[62,438,440,443,446],{"class":64,"line":439},23,[62,441,442],{"class":121},"    logging.info(",[62,444,445],{"class":111},"\"Starting daily Excel report.\"",[62,447,225],{"class":121},[62,449,451,454],{"class":64,"line":450},24,[62,452,453],{"class":117},"    try",[62,455,456],{"class":121},":\n",[62,458,460],{"class":64,"line":459},25,[62,461,462],{"class":189},"        # Build sample data so the run is self-contained.\n",[62,464,466,469,471],{"class":64,"line":465},26,[62,467,468],{"class":121},"        df ",[62,470,295],{"class":117},[62,472,473],{"class":121}," pd.DataFrame({\n",[62,475,477,480,483,486,488,491,493,495,497,500,502,504],{"class":64,"line":476},27,[62,478,479],{"class":111},"            \"region\"",[62,481,482],{"class":121},": [",[62,484,485],{"class":111},"\"North\"",[62,487,277],{"class":121},[62,489,490],{"class":111},"\"South\"",[62,492,277],{"class":121},[62,494,485],{"class":111},[62,496,277],{"class":121},[62,498,499],{"class":111},"\"East\"",[62,501,277],{"class":121},[62,503,490],{"class":111},[62,505,506],{"class":121},"],\n",[62,508,510,513,515,518,520,523,525,528,530,533,535,537],{"class":64,"line":509},28,[62,511,512],{"class":111},"            \"revenue\"",[62,514,482],{"class":121},[62,516,517],{"class":196},"1200.0",[62,519,277],{"class":121},[62,521,522],{"class":196},"980.5",[62,524,277],{"class":121},[62,526,527],{"class":196},"1450.0",[62,529,277],{"class":121},[62,531,532],{"class":196},"610.25",[62,534,277],{"class":121},[62,536,522],{"class":196},[62,538,506],{"class":121},[62,540,542],{"class":64,"line":541},29,[62,543,544],{"class":121},"        })\n",[62,546,548,551,553,556,559,561,564,566,569,572,575],{"class":64,"line":547},30,[62,549,550],{"class":121},"        summary ",[62,552,295],{"class":117},[62,554,555],{"class":121}," df.groupby(",[62,557,558],{"class":111},"\"region\"",[62,560,277],{"class":121},[62,562,563],{"class":291},"as_index",[62,565,295],{"class":117},[62,567,568],{"class":196},"False",[62,570,571],{"class":121},")[",[62,573,574],{"class":111},"\"revenue\"",[62,576,577],{"class":121},"].sum()\n",[62,579,581],{"class":64,"line":580},31,[62,582,164],{"emptyLinePlaceholder":163},[62,584,586,589,591,594,596],{"class":64,"line":585},32,[62,587,588],{"class":121},"        out ",[62,590,295],{"class":117},[62,592,593],{"class":196}," OUTPUT_DIR",[62,595,239],{"class":117},[62,597,598],{"class":111}," \"daily_summary.xlsx\"\n",[62,600,602,605,608,610,612,614,617,619,622],{"class":64,"line":601},33,[62,603,604],{"class":121},"        summary.to_excel(out, ",[62,606,607],{"class":291},"index",[62,609,295],{"class":117},[62,611,568],{"class":196},[62,613,277],{"class":121},[62,615,616],{"class":291},"engine",[62,618,295],{"class":117},[62,620,621],{"class":111},"\"openpyxl\"",[62,623,225],{"class":121},[62,625,627,630,633,636,639,642,644,646,649],{"class":64,"line":626},34,[62,628,629],{"class":121},"        logging.info(",[62,631,632],{"class":111},"\"Wrote ",[62,634,635],{"class":196},"%d",[62,637,638],{"class":111}," rows to ",[62,640,641],{"class":196},"%s",[62,643,209],{"class":111},[62,645,277],{"class":121},[62,647,648],{"class":196},"len",[62,650,651],{"class":121},"(summary), out)\n",[62,653,655,658,661],{"class":64,"line":654},35,[62,656,657],{"class":117},"    except",[62,659,660],{"class":196}," Exception",[62,662,456],{"class":121},[62,664,666,669,672],{"class":64,"line":665},36,[62,667,668],{"class":121},"        logging.exception(",[62,670,671],{"class":111},"\"Report generation failed.\"",[62,673,225],{"class":121},[62,675,677,680,683],{"class":64,"line":676},37,[62,678,679],{"class":121},"        sys.exit(",[62,681,682],{"class":196},"1",[62,684,225],{"class":121},[62,686,688,690,693],{"class":64,"line":687},38,[62,689,442],{"class":121},[62,691,692],{"class":111},"\"Done.\"",[62,694,225],{"class":121},[62,696,698],{"class":64,"line":697},39,[62,699,164],{"emptyLinePlaceholder":163},[62,701,703,706,709,712,715],{"class":64,"line":702},40,[62,704,705],{"class":117},"if",[62,707,708],{"class":196}," __name__",[62,710,711],{"class":117}," ==",[62,713,714],{"class":111}," \"__main__\"",[62,716,456],{"class":121},[62,718,720],{"class":64,"line":719},41,[62,721,722],{"class":121},"    main()\n",[10,724,725],{},"Confirm it runs from a normal prompt first:",[53,727,729],{"className":55,"code":728,"language":57,"meta":58,"style":58},"C:\\reporting\\venv\\Scripts\\python.exe C:\\reporting\\generate_daily_report.py\n",[14,730,731],{"__ignoreMap":58},[62,732,733],{"class":64,"line":65},[62,734,728],{},[38,736,738],{"id":737},"a-bat-wrapper-that-logs-stdout","A .bat wrapper that logs stdout",[10,740,741,742,745,746,749,750,754,755,758],{},"Task Scheduler can run ",[14,743,744],{},"python.exe"," directly, but a small ",[14,747,748],{},".bat"," wrapper gives you one place to capture stdout and stderr — the output that appears ",[751,752,753],"em",{},"before"," your in-script logging starts (a missing module, a syntax error). Save this as ",[14,756,757],{},"C:\\reporting\\run_report.bat",":",[53,760,762],{"className":55,"code":761,"language":57,"meta":58,"style":58},"@echo off\nREM Activate the venv, then run the report, appending all output to a log.\ncall C:\\reporting\\venv\\Scripts\\activate.bat\npython C:\\reporting\\generate_daily_report.py >> C:\\reporting\\logs\\stdout.log 2>&1\n",[14,763,764,769,774,779],{"__ignoreMap":58},[62,765,766],{"class":64,"line":65},[62,767,768],{},"@echo off\n",[62,770,771],{"class":64,"line":71},[62,772,773],{},"REM Activate the venv, then run the report, appending all output to a log.\n",[62,775,776],{"class":64,"line":125},[62,777,778],{},"call C:\\reporting\\venv\\Scripts\\activate.bat\n",[62,780,781],{"class":64,"line":133},[62,782,783],{},"python C:\\reporting\\generate_daily_report.py >> C:\\reporting\\logs\\stdout.log 2>&1\n",[10,785,786,787,790,791,794],{},"The ",[14,788,789],{},">> ... 2>&1"," redirect is the Windows equivalent of cron's ",[14,792,793],{},">> logfile 2>&1",": without it, interpreter-level errors go nowhere because Task Scheduler discards a task's console output.",[38,796,798],{"id":797},"register-the-task-with-schtasks","Register the task with schtasks",[10,800,801,802,805,806,809],{},"Open an ",[19,803,804],{},"elevated"," Command Prompt (Run as administrator). The ",[14,807,808],{},"^"," is the line-continuation character in batch — keep it on Windows, or put the whole command on one line.",[10,811,812],{},"Daily at 06:00:",[53,814,816],{"className":55,"code":815,"language":57,"meta":58,"style":58},"schtasks \u002FCreate \u002FTN \"DailyExcelReport\" \u002FSC DAILY \u002FST 06:00 ^\n  \u002FTR \"C:\\reporting\\run_report.bat\" \u002FRL HIGHEST \u002FF\n",[14,817,818,823],{"__ignoreMap":58},[62,819,820],{"class":64,"line":65},[62,821,822],{},"schtasks \u002FCreate \u002FTN \"DailyExcelReport\" \u002FSC DAILY \u002FST 06:00 ^\n",[62,824,825],{"class":64,"line":71},[62,826,827],{},"  \u002FTR \"C:\\reporting\\run_report.bat\" \u002FRL HIGHEST \u002FF\n",[10,829,830],{},"Weekdays only:",[53,832,834],{"className":55,"code":833,"language":57,"meta":58,"style":58},"schtasks \u002FCreate \u002FTN \"DailyExcelReport\" \u002FSC WEEKLY \u002FD MON,TUE,WED,THU,FRI \u002FST 07:30 ^\n  \u002FTR \"C:\\reporting\\run_report.bat\" \u002FRL HIGHEST \u002FF\n",[14,835,836,841],{"__ignoreMap":58},[62,837,838],{"class":64,"line":65},[62,839,840],{},"schtasks \u002FCreate \u002FTN \"DailyExcelReport\" \u002FSC WEEKLY \u002FD MON,TUE,WED,THU,FRI \u002FST 07:30 ^\n",[62,842,843],{"class":64,"line":71},[62,844,827],{},[10,846,847],{},"Every four hours:",[53,849,851],{"className":55,"code":850,"language":57,"meta":58,"style":58},"schtasks \u002FCreate \u002FTN \"HourlyExcelReport\" \u002FSC HOURLY \u002FMO 4 ^\n  \u002FTR \"C:\\reporting\\run_report.bat\" \u002FRL HIGHEST \u002FF\n",[14,852,853,858],{"__ignoreMap":58},[62,854,855],{"class":64,"line":65},[62,856,857],{},"schtasks \u002FCreate \u002FTN \"HourlyExcelReport\" \u002FSC HOURLY \u002FMO 4 ^\n",[62,859,860],{"class":64,"line":71},[62,861,827],{},[10,863,864,867],{},[14,865,866],{},"\u002FF"," overwrites an existing task with the same name, which makes the command safe to rerun when you redeploy.",[869,870,872],"h3",{"id":871},"run-whether-or-not-the-user-is-logged-on","Run whether or not the user is logged on",[10,874,875,876,879,880,883,884,758],{},"By default a task only fires while its user is interactively logged on. To run it regardless — the usual requirement for a server — supply credentials with ",[14,877,878],{},"\u002FRU"," and ",[14,881,882],{},"\u002FRP",", and request the highest privileges with ",[14,885,886],{},"\u002FRL HIGHEST",[53,888,890],{"className":55,"code":889,"language":57,"meta":58,"style":58},"schtasks \u002FCreate \u002FTN \"DailyExcelReport\" \u002FSC DAILY \u002FST 06:00 ^\n  \u002FTR \"C:\\reporting\\run_report.bat\" ^\n  \u002FRU \"DOMAIN\\svc_reports\" \u002FRP \"the-password\" \u002FRL HIGHEST \u002FF\n",[14,891,892,896,901],{"__ignoreMap":58},[62,893,894],{"class":64,"line":65},[62,895,822],{},[62,897,898],{"class":64,"line":71},[62,899,900],{},"  \u002FTR \"C:\\reporting\\run_report.bat\" ^\n",[62,902,903],{"class":64,"line":125},[62,904,905],{},"  \u002FRU \"DOMAIN\\svc_reports\" \u002FRP \"the-password\" \u002FRL HIGHEST \u002FF\n",[10,907,908,909,911,912,914],{},"Use a dedicated service account with a non-expiring password for ",[14,910,878],{},". If you omit ",[14,913,882],{},", Windows prompts for the password interactively.",[38,916,918],{"id":917},"schtasks-create-field-reference","schtasks \u002FCreate field reference",[920,921,922,938],"table",{},[923,924,925],"thead",{},[926,927,928,932,935],"tr",{},[929,930,931],"th",{},"Flag",[929,933,934],{},"Meaning",[929,936,937],{},"Example",[939,940,941,957,972,999,1017,1035,1053,1067,1081,1100],"tbody",{},[926,942,943,949,952],{},[944,945,946],"td",{},[14,947,948],{},"\u002FTN",[944,950,951],{},"Task name (must be unique)",[944,953,954],{},[14,955,956],{},"\"DailyExcelReport\"",[926,958,959,964,967],{},[944,960,961],{},[14,962,963],{},"\u002FTR",[944,965,966],{},"Task to run — the program or .bat",[944,968,969],{},[14,970,971],{},"\"C:\\reporting\\run_report.bat\"",[926,973,974,979,982],{},[944,975,976],{},[14,977,978],{},"\u002FSC",[944,980,981],{},"Schedule type",[944,983,984,277,987,277,990,277,993,277,996],{},[14,985,986],{},"DAILY",[14,988,989],{},"WEEKLY",[14,991,992],{},"HOURLY",[14,994,995],{},"MINUTE",[14,997,998],{},"ONLOGON",[926,1000,1001,1006,1012],{},[944,1002,1003],{},[14,1004,1005],{},"\u002FST",[944,1007,1008,1009],{},"Start time, 24-hour ",[14,1010,1011],{},"HH:MM",[944,1013,1014],{},[14,1015,1016],{},"06:00",[926,1018,1019,1024,1030],{},[944,1020,1021],{},[14,1022,1023],{},"\u002FD",[944,1025,1026,1027,1029],{},"Days (with ",[14,1028,989],{},")",[944,1031,1032],{},[14,1033,1034],{},"MON,TUE,WED,THU,FRI",[926,1036,1037,1042,1045],{},[944,1038,1039],{},[14,1040,1041],{},"\u002FMO",[944,1043,1044],{},"Modifier \u002F interval",[944,1046,1047,1050,1051,1029],{},[14,1048,1049],{},"4"," (every 4 hours with ",[14,1052,992],{},[926,1054,1055,1059,1062],{},[944,1056,1057],{},[14,1058,878],{},[944,1060,1061],{},"Run-as user account",[944,1063,1064],{},[14,1065,1066],{},"\"DOMAIN\\svc_reports\"",[926,1068,1069,1073,1076],{},[944,1070,1071],{},[14,1072,882],{},[944,1074,1075],{},"Run-as password",[944,1077,1078],{},[14,1079,1080],{},"\"the-password\"",[926,1082,1083,1088,1091],{},[944,1084,1085],{},[14,1086,1087],{},"\u002FRL",[944,1089,1090],{},"Run level",[944,1092,1093,1096,1097],{},[14,1094,1095],{},"HIGHEST"," or ",[14,1098,1099],{},"LIMITED",[926,1101,1102,1106,1109],{},[944,1103,1104],{},[14,1105,866],{},[944,1107,1108],{},"Force-overwrite an existing task",[944,1110,1111],{},"(no value)",[38,1113,1115],{"id":1114},"the-task-scheduler-gui-briefly","The Task Scheduler GUI, briefly",[10,1117,1118,1119,272,1121,1124,1125,1128,1129,1132,1133,1136,1137,1139,1140,1143,1144,1147,1148,879,1151,1154,1155,1157],{},"If you prefer the GUI, open ",[19,1120,21],{},[14,1122,1123],{},"taskschd.msc",") → ",[751,1126,1127],{},"Create Task",". On the ",[19,1130,1131],{},"Actions"," tab set ",[751,1134,1135],{},"Program\u002Fscript"," to ",[14,1138,757],{},". On ",[19,1141,1142],{},"Triggers"," add a daily\u002Fweekly schedule. On the ",[19,1145,1146],{},"General"," tab tick ",[751,1149,1150],{},"Run whether user is logged on or not",[751,1152,1153],{},"Run with highest privileges",". The result is identical to the ",[14,1156,25],{}," command above — the CLI is just reproducible.",[38,1159,1161],{"id":1160},"verify-the-task","Verify the task",[10,1163,1164],{},"List the task and read its scheduling and last result:",[53,1166,1168],{"className":55,"code":1167,"language":57,"meta":58,"style":58},"schtasks \u002FQuery \u002FTN \"DailyExcelReport\" \u002FV \u002FFO LIST\n",[14,1169,1170],{"__ignoreMap":58},[62,1171,1172],{"class":64,"line":65},[62,1173,1167],{},[10,1175,786,1176,1178],{},[19,1177,98],{}," field is what tells you whether the run succeeded:",[920,1180,1181,1189],{},[923,1182,1183],{},[926,1184,1185,1187],{},[929,1186,98],{},[929,1188,934],{},[939,1190,1191,1201,1214,1227,1237],{},[926,1192,1193,1198],{},[944,1194,1195],{},[14,1196,1197],{},"0x0",[944,1199,1200],{},"Success",[926,1202,1203,1208],{},[944,1204,1205],{},[14,1206,1207],{},"0x1",[944,1209,1210,1211,1029],{},"Incorrect function \u002F the script exited non-zero (your ",[14,1212,1213],{},"sys.exit(1)",[926,1215,1216,1221],{},[944,1217,1218],{},[14,1219,1220],{},"0x2",[944,1222,1223,1224,1226],{},"File not found (check the ",[14,1225,963],{}," path)",[926,1228,1229,1234],{},[944,1230,1231],{},[14,1232,1233],{},"0x41301",[944,1235,1236],{},"Task is currently running",[926,1238,1239,1244],{},[944,1240,1241],{},[14,1242,1243],{},"267011",[944,1245,1246],{},"Task has not yet run",[10,1248,1249],{},"Force an immediate run to test without waiting for the schedule:",[53,1251,1253],{"className":55,"code":1252,"language":57,"meta":58,"style":58},"schtasks \u002FRun \u002FTN \"DailyExcelReport\"\n",[14,1254,1255],{"__ignoreMap":58},[62,1256,1257],{"class":64,"line":65},[62,1258,1252],{},[10,1260,1261,1262,1265,1266,1269],{},"Then confirm ",[14,1263,1264],{},"C:\\reporting\\output\\daily_summary.xlsx"," was written and check ",[14,1267,1268],{},"C:\\reporting\\logs\\stdout.log",".",[38,1271,1273],{"id":1272},"common-pitfalls","Common pitfalls",[920,1275,1276,1289],{},[923,1277,1278],{},[926,1279,1280,1283,1286],{},[929,1281,1282],{},"Symptom",[929,1284,1285],{},"Cause",[929,1287,1288],{},"Fix",[939,1290,1291,1309,1325,1344,1357],{},[926,1292,1293,1299,1306],{},[944,1294,1295,1298],{},[14,1296,1297],{},"FileNotFoundError"," for a file you can see",[944,1300,1301,1302,1305],{},"Working directory is ",[14,1303,1304],{},"System32",", not your script folder",[944,1307,1308],{},"Use absolute paths for every read and write",[926,1310,1311,1316,1319],{},[944,1312,1313],{},[14,1314,1315],{},"ModuleNotFoundError: pandas",[944,1317,1318],{},"Task ran the system Python, not the venv",[944,1320,1321,1322,1324],{},"Call ",[14,1323,80],{}," (or activate in the .bat)",[926,1326,1327,1332,1338],{},[944,1328,1329,1330],{},"Last Run Result ",[14,1331,1220],{},[944,1333,1334,1335,1337],{},"Path in ",[14,1336,963],{}," has spaces and isn't quoted",[944,1339,1340,1341,1343],{},"Wrap the whole ",[14,1342,963],{}," value in double quotes",[926,1345,1346,1349,1352],{},[944,1347,1348],{},"Task \"succeeds\" but no file appears",[944,1350,1351],{},"Output and errors discarded",[944,1353,1354,1355],{},"Redirect in the .bat with ",[14,1356,793],{},[926,1358,1359,1362,1371],{},[944,1360,1361],{},"Runs only when you're logged in",[944,1363,1364,1365,1367,1368,1370],{},"No ",[14,1366,878],{}," \u002F ",[14,1369,882],{}," supplied",[944,1372,1373,1374],{},"Add a service account and ",[14,1375,886],{},[10,1377,1378,1379,1382,1383,1386,1387,1389,1390,1393],{},"A note on quoting: paths with spaces (",[14,1380,1381],{},"C:\\Program Files\\...",") need quotes ",[751,1384,1385],{},"inside"," the already-quoted ",[14,1388,963],{}," string, which is awkward. Installing your project under a space-free path like ",[14,1391,1392],{},"C:\\reporting"," avoids the problem entirely.",[38,1395,1397],{"id":1396},"frequently-asked-questions","Frequently asked questions",[10,1399,1400,1403,1404,1407],{},[19,1401,1402],{},"Do I need the .bat wrapper, or can I point the task straight at python.exe?","\nYou can set ",[14,1405,1406],{},"\u002FTR \"C:\\reporting\\venv\\Scripts\\python.exe C:\\reporting\\generate_daily_report.py\""," directly. The wrapper is worth it because it gives you one tidy place to capture stdout\u002Fstderr to a log and to activate the venv if other tooling expects it.",[10,1409,1410,1413,1414,1417,1418,1421,1422,1424],{},[19,1411,1412],{},"Why does the task run fine manually but fail on schedule?","\nAlmost always the run-as context. A manual ",[14,1415,1416],{},"\u002FRun"," uses your logged-on session; the scheduled run may use a service account with a different ",[14,1419,1420],{},"PATH"," and working directory. Use absolute paths and confirm the ",[14,1423,878],{}," account can read the script and write the output folder.",[10,1426,1427,1430,1433,1434,1437,1438,1440,1441,1444,1445,1269],{},[19,1428,1429],{},"How do I delete or change a task?",[14,1431,1432],{},"schtasks \u002FDelete \u002FTN \"DailyExcelReport\" \u002FF"," removes it. To change it, rerun ",[14,1435,1436],{},"\u002FCreate"," with ",[14,1439,866],{}," to overwrite, or use ",[14,1442,1443],{},"schtasks \u002FChange"," to tweak a single setting like ",[14,1446,1005],{},[10,1448,1449,1452,1453,1269],{},[19,1450,1451],{},"Can Task Scheduler email the report after it runs?","\nNot directly — its built-in email action is deprecated. Send mail from Python at the end of the job; see ",[28,1454,1456],{"href":1455},"\u002Fautomating-reporting-workflows\u002Femailing-excel-reports-with-smtplib\u002F","Emailing Excel Reports with smtplib",[38,1458,1460],{"id":1459},"conclusion","Conclusion",[10,1462,1463,1464,1466,1467,1469,1470,1472,1473,1475,1476,1475,1478,1480,1481,1484,1485,1488,1489,1491],{},"Scheduling a Python Excel script on Windows comes down to four things: call the venv ",[14,1465,744],{}," by absolute path, use absolute paths inside the script (the working directory is ",[14,1468,1304],{},"), redirect output to a log in a ",[14,1471,748],{}," wrapper, and add ",[14,1474,878],{},"\u002F",[14,1477,882],{},[14,1479,886],{}," so the task runs while logged off. Register it with ",[14,1482,1483],{},"schtasks \u002FCreate \u002FF",", verify with ",[14,1486,1487],{},"schtasks \u002FQuery \u002FV",", and key your monitoring off the ",[19,1490,98],{}," code.",[38,1493,1495],{"id":1494},"where-to-go-next","Where to go next",[10,1497,1498,1499,1501,1502,1506,1507,1511,1512,1269],{},"This is the Windows track of ",[28,1500,31],{"href":30},". If you'd rather schedule inside Python and stay cross-platform, see the sibling guide ",[28,1503,1505],{"href":1504},"\u002Fautomating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Fschedule-recurring-excel-reports-with-apscheduler\u002F","Schedule Recurring Excel Reports with APScheduler",". To strengthen the report the task produces, see ",[28,1508,1510],{"href":1509},"\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002F","Writing DataFrames to Excel with pandas",", and to deliver it, ",[28,1513,1456],{"href":1455},[1515,1516,1517],"style",{},"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 .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sA_wV, html code.shiki .sA_wV{--shiki-default:#032F62;--shiki-dark:#DBEDFF}html pre.shiki code .snhLl, html code.shiki .snhLl{--shiki-default:#22863A;--shiki-default-font-weight:bold;--shiki-dark:#85E89D;--shiki-dark-font-weight:bold}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":58,"searchDepth":71,"depth":71,"links":1519},[1520,1521,1522,1523,1526,1527,1528,1529,1530,1531,1532],{"id":40,"depth":71,"text":41},{"id":84,"depth":71,"text":85},{"id":737,"depth":71,"text":738},{"id":797,"depth":71,"text":798,"children":1524},[1525],{"id":871,"depth":125,"text":872},{"id":917,"depth":71,"text":918},{"id":1114,"depth":71,"text":1115},{"id":1160,"depth":71,"text":1161},{"id":1272,"depth":71,"text":1273},{"id":1396,"depth":71,"text":1397},{"id":1459,"depth":71,"text":1460},{"id":1494,"depth":71,"text":1495},"Register a Python Excel report with Windows Task Scheduler: a self-contained generator, schtasks \u002FCreate triggers, the venv interpreter, a .bat wrapper, and logging.","md",{},"\u002Fautomating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Frun-python-excel-script-on-windows-task-scheduler",{"title":1538,"description":1539},"Run a Python Excel Script on Task Scheduler","Schedule a Python Excel report on Windows with schtasks: daily, weekly, and hourly triggers, the venv python.exe by absolute path, a logging .bat wrapper, verification.","automating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Frun-python-excel-script-on-windows-task-scheduler\u002Findex","TXeVFxNjoQiC6DRFaj5IJ3QilZBJ3Ex1a9N0PMBEmjY",[1543,1546],{"title":31,"path":1544,"stem":1545,"children":-1},"\u002Fautomating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron","automating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Findex",{"title":1505,"path":1547,"stem":1548,"children":-1},"\u002Fautomating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Fschedule-recurring-excel-reports-with-apscheduler","automating-reporting-workflows\u002Fscheduling-python-excel-scripts-with-cron\u002Fschedule-recurring-excel-reports-with-apscheduler\u002Findex",1781773160963]