[{"data":1,"prerenderedAt":1945},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fprint-an-excel-workbook-from-python-with-win32com":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fprint-an-excel-workbook-from-python-with-win32com":1916,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fprint-an-excel-workbook-from-python-with-win32com":1924,"children:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fprint-an-excel-workbook-from-python-with-win32com":1929,"related:\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fprint-an-excel-workbook-from-python-with-win32com":1930},{"id":4,"title":5,"body":6,"dateModified":1882,"datePublished":1882,"description":1883,"extension":1884,"faq":1885,"keyword":1894,"kind":1895,"meta":1896,"navigation":108,"path":1905,"seo":1906,"slug":1909,"stem":1910,"topics":1911,"type":1914,"__hash__":1915},"docs\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fprint-an-excel-workbook-from-python-with-win32com\u002Findex.md","Print an Excel Workbook from Python with win32com",{"type":7,"value":8,"toc":1869},"minimark",[9,19,24,53,60,64,67,372,386,542,546,656,666,670,828,856,863,933,945,1073,1077,1316,1335,1339,1342,1521,1532,1536,1539,1561,1576,1711,1715,1776,1780,1804,1808,1814,1820,1826,1832,1836,1865],[10,11,12,13,18],"p",{},"Some reports still end on paper: delivery notes for the warehouse, a daily schedule pinned to a wall, monthly packs for a board that reads in print. When a script already produces the workbooks, sending them to the printer is the last step to automate. On Windows with Excel installed, the COM interface gives Python the same printing Excel's own menu uses — choose a printer, print the whole workbook or one sheet, set copies and page ranges — without any dialog popping up. The part people get wrong is not the print call but the page setup: a sheet that is one column too wide prints on twice as many pages. This page covers both, plus what to do on a machine without Excel. It belongs to ",[14,15,17],"a",{"href":16},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002F","Automating Excel with COM and pywin32",".",[20,21,23],"h2",{"id":22},"prerequisites","Prerequisites",[25,26,31],"pre",{"className":27,"code":28,"language":29,"meta":30,"style":30},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pywin32 openpyxl\n","bash","",[32,33,34],"code",{"__ignoreMap":30},[35,36,39,43,47,50],"span",{"class":37,"line":38},"line",1,[35,40,42],{"class":41},"sMTad","pip",[35,44,46],{"class":45},"srMev"," install",[35,48,49],{"class":45}," pywin32",[35,51,52],{"class":45}," openpyxl\n",[10,54,55,56,59],{},"Printing through COM requires Windows with Excel installed and a configured printer; those steps are marked as not run by our build, which runs on Linux. The page-setup step uses openpyxl and runs anywhere. The example file ",[32,57,58],{},"deliveries.xlsx"," is a 120-row delivery route with twelve columns — too wide for a portrait page — that should print landscape, one page wide, with the header row repeated on every page.",[20,61,63],{"id":62},"step-1-get-the-page-setup-right-first","Step 1 — Get the page setup right first",[10,65,66],{},"Print settings are stored in the workbook, so they can be prepared by the script that builds the report — on any operating system — and Excel uses them when it prints:",[25,68,72],{"className":69,"code":70,"language":71,"meta":30,"style":30},"language-python shiki shiki-themes github-light github-dark-high-contrast","from openpyxl import load_workbook\nfrom openpyxl.utils import get_column_letter\n\nwb = load_workbook(\"deliveries.xlsx\")\nws = wb[\"Route\"]\nws.page_setup.orientation = \"landscape\"\nws.page_setup.paperSize = ws.PAPERSIZE_A4\nws.sheet_properties.pageSetUpPr.fitToPage = True\nws.page_setup.fitToWidth = 1          # one page wide\nws.page_setup.fitToHeight = 0         # as many pages tall as needed\nws.print_title_rows = \"1:1\"           # repeat the header on every page\nws.print_area = f\"A1:{get_column_letter(ws.max_column)}{ws.max_row}\"\nfor col in range(1, ws.max_column + 1):\n    ws.column_dimensions[get_column_letter(col)].width = 14\nws.oddFooter.center.text = \"Page &P of &N\"\nws.print_options.gridLines = True\nwb.save(\"deliveries_print.xlsx\")\n\ncheck = load_workbook(\"deliveries_print.xlsx\")[\"Route\"]\nprint(check.page_setup.orientation, check.page_setup.fitToWidth, check.page_setup.fitToHeight,\n      check.print_title_rows, check.print_area)\n","python",[32,73,74,90,103,110,128,145,156,171,182,197,211,225,258,290,301,312,322,333,338,357,366],{"__ignoreMap":30},[35,75,76,80,84,87],{"class":37,"line":38},[35,77,79],{"class":78},"s-kum","from",[35,81,83],{"class":82},"skGVy"," openpyxl ",[35,85,86],{"class":78},"import",[35,88,89],{"class":82}," load_workbook\n",[35,91,93,95,98,100],{"class":37,"line":92},2,[35,94,79],{"class":78},[35,96,97],{"class":82}," openpyxl.utils ",[35,99,86],{"class":78},[35,101,102],{"class":82}," get_column_letter\n",[35,104,106],{"class":37,"line":105},3,[35,107,109],{"emptyLinePlaceholder":108},true,"\n",[35,111,113,116,119,122,125],{"class":37,"line":112},4,[35,114,115],{"class":82},"wb ",[35,117,118],{"class":78},"=",[35,120,121],{"class":82}," load_workbook(",[35,123,124],{"class":45},"\"deliveries.xlsx\"",[35,126,127],{"class":82},")\n",[35,129,131,134,136,139,142],{"class":37,"line":130},5,[35,132,133],{"class":82},"ws ",[35,135,118],{"class":78},[35,137,138],{"class":82}," wb[",[35,140,141],{"class":45},"\"Route\"",[35,143,144],{"class":82},"]\n",[35,146,148,151,153],{"class":37,"line":147},6,[35,149,150],{"class":82},"ws.page_setup.orientation ",[35,152,118],{"class":78},[35,154,155],{"class":45}," \"landscape\"\n",[35,157,159,162,164,167],{"class":37,"line":158},7,[35,160,161],{"class":82},"ws.page_setup.paperSize ",[35,163,118],{"class":78},[35,165,166],{"class":82}," ws.",[35,168,170],{"class":169},"sP0c6","PAPERSIZE_A4\n",[35,172,174,177,179],{"class":37,"line":173},8,[35,175,176],{"class":82},"ws.sheet_properties.pageSetUpPr.fitToPage ",[35,178,118],{"class":78},[35,180,181],{"class":169}," True\n",[35,183,185,188,190,193],{"class":37,"line":184},9,[35,186,187],{"class":82},"ws.page_setup.fitToWidth ",[35,189,118],{"class":78},[35,191,192],{"class":169}," 1",[35,194,196],{"class":195},"s-wDw","          # one page wide\n",[35,198,200,203,205,208],{"class":37,"line":199},10,[35,201,202],{"class":82},"ws.page_setup.fitToHeight ",[35,204,118],{"class":78},[35,206,207],{"class":169}," 0",[35,209,210],{"class":195},"         # as many pages tall as needed\n",[35,212,214,217,219,222],{"class":37,"line":213},11,[35,215,216],{"class":82},"ws.print_title_rows ",[35,218,118],{"class":78},[35,220,221],{"class":45}," \"1:1\"",[35,223,224],{"class":195},"           # repeat the header on every page\n",[35,226,228,231,233,236,239,243,246,249,252,255],{"class":37,"line":227},12,[35,229,230],{"class":82},"ws.print_area ",[35,232,118],{"class":78},[35,234,235],{"class":78}," f",[35,237,238],{"class":45},"\"A1:",[35,240,242],{"class":241},"sSjpA","{",[35,244,245],{"class":82},"get_column_letter(ws.max_column)",[35,247,248],{"class":241},"}{",[35,250,251],{"class":82},"ws.max_row",[35,253,254],{"class":241},"}",[35,256,257],{"class":45},"\"\n",[35,259,261,264,267,270,273,276,279,282,285,287],{"class":37,"line":260},13,[35,262,263],{"class":78},"for",[35,265,266],{"class":82}," col ",[35,268,269],{"class":78},"in",[35,271,272],{"class":169}," range",[35,274,275],{"class":82},"(",[35,277,278],{"class":169},"1",[35,280,281],{"class":82},", ws.max_column ",[35,283,284],{"class":78},"+",[35,286,192],{"class":169},[35,288,289],{"class":82},"):\n",[35,291,293,296,298],{"class":37,"line":292},14,[35,294,295],{"class":82},"    ws.column_dimensions[get_column_letter(col)].width ",[35,297,118],{"class":78},[35,299,300],{"class":169}," 14\n",[35,302,304,307,309],{"class":37,"line":303},15,[35,305,306],{"class":82},"ws.oddFooter.center.text ",[35,308,118],{"class":78},[35,310,311],{"class":45}," \"Page &P of &N\"\n",[35,313,315,318,320],{"class":37,"line":314},16,[35,316,317],{"class":82},"ws.print_options.gridLines ",[35,319,118],{"class":78},[35,321,181],{"class":169},[35,323,325,328,331],{"class":37,"line":324},17,[35,326,327],{"class":82},"wb.save(",[35,329,330],{"class":45},"\"deliveries_print.xlsx\"",[35,332,127],{"class":82},[35,334,336],{"class":37,"line":335},18,[35,337,109],{"emptyLinePlaceholder":108},[35,339,341,344,346,348,350,353,355],{"class":37,"line":340},19,[35,342,343],{"class":82},"check ",[35,345,118],{"class":78},[35,347,121],{"class":82},[35,349,330],{"class":45},[35,351,352],{"class":82},")[",[35,354,141],{"class":45},[35,356,144],{"class":82},[35,358,360,363],{"class":37,"line":359},20,[35,361,362],{"class":169},"print",[35,364,365],{"class":82},"(check.page_setup.orientation, check.page_setup.fitToWidth, check.page_setup.fitToHeight,\n",[35,367,369],{"class":37,"line":368},21,[35,370,371],{"class":82},"      check.print_title_rows, check.print_area)\n",[10,373,374,377,378,381,382,18],{},[32,375,376],{},"fitToPage"," must be switched on for the fit-to settings to apply; ",[32,379,380],{},"fitToHeight = 0"," means \"no limit\", so long tables flow onto as many pages as they need while never spilling sideways. Repeating row 1 keeps every page readable on its own, and the footer numbers the pages. These settings are covered in detail in ",[14,383,385],{"href":384},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fset-print-area-and-page-setup-with-openpyxl\u002F","Set the Print Area and Page Setup with openpyxl",[387,388,396,397,396,401,396,405,396,413,396,423,396,434,396,441,396,447,396,453,396,461,396,465,396,470,396,474,396,479,396,483,396,488,396,493,396,500,396,505,396,509,396,513,396,518,396,521,396,526,396,529,396,534,396,537],"svg",{"viewBox":389,"role":390,"ariaLabelledBy":391,"xmlns":394,"style":395},"4 0 752 233","img",[392,393],"pr-setup-t","pr-setup-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[398,399,400],"title",{"id":392},"The same sheet printed with and without fit-to-width",[402,403,404],"desc",{"id":393},"Without page setup, twelve columns spill onto extra pages sideways and the header appears only on the first page. With landscape orientation, fit to one page wide and a repeated title row, every page shows all columns and the header.",[406,407],"rect",{"x":408,"y":409,"width":410,"height":411,"fill":412},"4","0","752","233","#ffffff",[406,414],{"x":415,"y":416,"width":417,"height":418,"rx":419,"fill":420,"stroke":421,"style":422},"20.0","16.0","351.0","201.0","14","#fce9e9","var(--danger,#dc2626)","stroke-width:2px",[424,425,427],"g",{"transform":426},"translate(182.5,29.0) scale(1.083)",[428,429],"path",{"d":430,"fill":431,"stroke":432,"style":433},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","none","var(--accent-ink,#be185d)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[435,436,440],"text",{"x":437,"y":438,"style":439},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","Default settings",[37,442],{"x1":443,"y1":444,"x2":445,"y2":444,"stroke":421,"style":446},"36.0","91.0","355.0","stroke-width:1px",[435,448,452],{"x":449,"y":450,"style":451},"60.0","111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","portrait, 100% scale",[424,454,456],{"transform":455},"translate(38.5,99.5) scale(0.625)",[428,457],{"d":458,"fill":431,"stroke":459,"style":460},"M6 6l12 12 M18 6L6 18","var(--accent,#f43f8f)","stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[435,462,464],{"x":449,"y":463,"style":451},"137.0","last column on a separate page",[424,466,468],{"transform":467},"translate(38.5,125.5) scale(0.625)",[428,469],{"d":458,"fill":431,"stroke":459,"style":460},[435,471,473],{"x":449,"y":472,"style":451},"163.0","header only on page 1",[424,475,477],{"transform":476},"translate(38.5,151.5) scale(0.625)",[428,478],{"d":458,"fill":431,"stroke":459,"style":460},[435,480,482],{"x":449,"y":481,"style":451},"189.0","no page numbers",[424,484,486],{"transform":485},"translate(38.5,177.5) scale(0.625)",[428,487],{"d":458,"fill":431,"stroke":459,"style":460},[406,489],{"x":490,"y":416,"width":417,"height":418,"rx":419,"fill":491,"stroke":492,"style":422},"389.0","#d9f4f1","var(--teal,#0f9488)",[424,494,496],{"transform":495},"translate(551.5,29.0) scale(1.083)",[428,497],{"d":498,"fill":431,"stroke":499,"style":433},"M5 12.5l4.5 4.5L19 7","var(--teal-ink,#0b6157)",[435,501,504],{"x":502,"y":438,"style":503},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Prepared page setup",[37,506],{"x1":507,"y1":444,"x2":508,"y2":444,"stroke":492,"style":446},"405.0","724.0",[435,510,512],{"x":511,"y":450,"style":451},"429.0","landscape, fit to 1 page wide",[424,514,516],{"transform":515},"translate(407.5,99.5) scale(0.625)",[428,517],{"d":498,"fill":431,"stroke":492,"style":460},[435,519,520],{"x":511,"y":463,"style":451},"every column on every page",[424,522,524],{"transform":523},"translate(407.5,125.5) scale(0.625)",[428,525],{"d":498,"fill":431,"stroke":492,"style":460},[435,527,528],{"x":511,"y":472,"style":451},"row 1 repeated on each page",[424,530,532],{"transform":531},"translate(407.5,151.5) scale(0.625)",[428,533],{"d":498,"fill":431,"stroke":492,"style":460},[435,535,536],{"x":511,"y":481,"style":451},"Page x of y in the footer",[424,538,540],{"transform":539},"translate(407.5,177.5) scale(0.625)",[428,541],{"d":498,"fill":431,"stroke":492,"style":460},[20,543,545],{"id":544},"step-2-list-printers-and-pick-one","Step 2 — List printers and pick one",[25,547,549],{"className":69,"code":548,"language":71,"meta":30,"style":30},"import win32print\n\ndefault = win32print.GetDefaultPrinter()\nflags = win32print.PRINTER_ENUM_LOCAL | win32print.PRINTER_ENUM_CONNECTIONS\nprinters = [p[2] for p in win32print.EnumPrinters(flags)]\nprint(\"default:\", default)\nfor name in printers:\n    print(\" \", name)\n",[32,550,551,558,562,572,593,619,631,643],{"__ignoreMap":30},[35,552,553,555],{"class":37,"line":38},[35,554,86],{"class":78},[35,556,557],{"class":82}," win32print\n",[35,559,560],{"class":37,"line":92},[35,561,109],{"emptyLinePlaceholder":108},[35,563,564,567,569],{"class":37,"line":105},[35,565,566],{"class":82},"default ",[35,568,118],{"class":78},[35,570,571],{"class":82}," win32print.GetDefaultPrinter()\n",[35,573,574,577,579,582,585,588,590],{"class":37,"line":112},[35,575,576],{"class":82},"flags ",[35,578,118],{"class":78},[35,580,581],{"class":82}," win32print.",[35,583,584],{"class":169},"PRINTER_ENUM_LOCAL",[35,586,587],{"class":78}," |",[35,589,581],{"class":82},[35,591,592],{"class":169},"PRINTER_ENUM_CONNECTIONS\n",[35,594,595,598,600,603,606,609,611,614,616],{"class":37,"line":130},[35,596,597],{"class":82},"printers ",[35,599,118],{"class":78},[35,601,602],{"class":82}," [p[",[35,604,605],{"class":169},"2",[35,607,608],{"class":82},"] ",[35,610,263],{"class":78},[35,612,613],{"class":82}," p ",[35,615,269],{"class":78},[35,617,618],{"class":82}," win32print.EnumPrinters(flags)]\n",[35,620,621,623,625,628],{"class":37,"line":147},[35,622,362],{"class":169},[35,624,275],{"class":82},[35,626,627],{"class":45},"\"default:\"",[35,629,630],{"class":82},", default)\n",[35,632,633,635,638,640],{"class":37,"line":158},[35,634,263],{"class":78},[35,636,637],{"class":82}," name ",[35,639,269],{"class":78},[35,641,642],{"class":82}," printers:\n",[35,644,645,648,650,653],{"class":37,"line":173},[35,646,647],{"class":169},"    print",[35,649,275],{"class":82},[35,651,652],{"class":45},"\" \"",[35,654,655],{"class":82},", name)\n",[10,657,658,661,662,665],{},[32,659,660],{},"EnumPrinters"," with the local and connections flags lists printers installed on the machine and shared network printers; element ",[32,663,664],{},"[2]"," of each entry is the printer name. A job running unattended should not rely on the default printer, which a user can change at any time — read the intended printer's name from configuration and check that it is in this list before printing.",[20,667,669],{"id":668},"step-3-print-with-printout","Step 3 — Print with PrintOut",[25,671,673],{"className":69,"code":672,"language":71,"meta":30,"style":30},"import os\nimport win32com.client as win32\n\nexcel = win32.DispatchEx(\"Excel.Application\")\nexcel.Visible = False\nexcel.DisplayAlerts = False\ntry:\n    wb = excel.Workbooks.Open(os.path.abspath(\"deliveries_print.xlsx\"), ReadOnly=True)\n    wb.PrintOut(Copies=1, ActivePrinter=\"Warehouse Laser\", Collate=True)\n    wb.Close(SaveChanges=False)\nfinally:\n    excel.Quit()\n",[32,674,675,682,695,699,714,724,733,741,767,801,816,823],{"__ignoreMap":30},[35,676,677,679],{"class":37,"line":38},[35,678,86],{"class":78},[35,680,681],{"class":82}," os\n",[35,683,684,686,689,692],{"class":37,"line":92},[35,685,86],{"class":78},[35,687,688],{"class":82}," win32com.client ",[35,690,691],{"class":78},"as",[35,693,694],{"class":82}," win32\n",[35,696,697],{"class":37,"line":105},[35,698,109],{"emptyLinePlaceholder":108},[35,700,701,704,706,709,712],{"class":37,"line":112},[35,702,703],{"class":82},"excel ",[35,705,118],{"class":78},[35,707,708],{"class":82}," win32.DispatchEx(",[35,710,711],{"class":45},"\"Excel.Application\"",[35,713,127],{"class":82},[35,715,716,719,721],{"class":37,"line":130},[35,717,718],{"class":82},"excel.Visible ",[35,720,118],{"class":78},[35,722,723],{"class":169}," False\n",[35,725,726,729,731],{"class":37,"line":147},[35,727,728],{"class":82},"excel.DisplayAlerts ",[35,730,118],{"class":78},[35,732,723],{"class":169},[35,734,735,738],{"class":37,"line":158},[35,736,737],{"class":78},"try",[35,739,740],{"class":82},":\n",[35,742,743,746,748,751,753,756,760,762,765],{"class":37,"line":173},[35,744,745],{"class":82},"    wb ",[35,747,118],{"class":78},[35,749,750],{"class":82}," excel.Workbooks.Open(os.path.abspath(",[35,752,330],{"class":45},[35,754,755],{"class":82},"), ",[35,757,759],{"class":758},"sa561","ReadOnly",[35,761,118],{"class":78},[35,763,764],{"class":169},"True",[35,766,127],{"class":82},[35,768,769,772,775,777,779,782,785,787,790,792,795,797,799],{"class":37,"line":184},[35,770,771],{"class":82},"    wb.PrintOut(",[35,773,774],{"class":758},"Copies",[35,776,118],{"class":78},[35,778,278],{"class":169},[35,780,781],{"class":82},", ",[35,783,784],{"class":758},"ActivePrinter",[35,786,118],{"class":78},[35,788,789],{"class":45},"\"Warehouse Laser\"",[35,791,781],{"class":82},[35,793,794],{"class":758},"Collate",[35,796,118],{"class":78},[35,798,764],{"class":169},[35,800,127],{"class":82},[35,802,803,806,809,811,814],{"class":37,"line":199},[35,804,805],{"class":82},"    wb.Close(",[35,807,808],{"class":758},"SaveChanges",[35,810,118],{"class":78},[35,812,813],{"class":169},"False",[35,815,127],{"class":82},[35,817,818,821],{"class":37,"line":213},[35,819,820],{"class":78},"finally",[35,822,740],{"class":82},[35,824,825],{"class":37,"line":227},[35,826,827],{"class":82},"    excel.Quit()\n",[10,829,830,833,834,836,837,840,841,844,845,847,848,851,852,18],{},[32,831,832],{},"Workbook.PrintOut"," prints every sheet with its own page setup; ",[32,835,784],{}," chooses the printer by name for this job. ",[32,838,839],{},"DispatchEx"," starts a separate Excel instance so the script does not interfere with a workbook the user has open, ",[32,842,843],{},"ReadOnly=True"," avoids locking the file, and the ",[32,846,820],{}," block makes sure Excel quits even if printing fails — a stray invisible ",[32,849,850],{},"EXCEL.EXE"," left behind is the classic COM problem, discussed in ",[14,853,855],{"href":854},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fclose-excel-cleanly-and-avoid-orphan-com-processes\u002F","Close Excel Cleanly and Avoid Orphan COM Processes",[10,857,858,859,862],{},"To print part of a workbook, call ",[32,860,861],{},"PrintOut"," on a sheet instead, with a page range:",[25,864,866],{"className":69,"code":865,"language":71,"meta":30,"style":30},"sheet = wb.Worksheets(\"Route\")\nsheet.PrintOut(From=1, To=2, Copies=2, ActivePrinter=\"Warehouse Laser\")\nprint(\"pages in the printout:\", sheet.PageSetup.Pages.Count)\n",[32,867,868,882,921],{"__ignoreMap":30},[35,869,870,873,875,878,880],{"class":37,"line":38},[35,871,872],{"class":82},"sheet ",[35,874,118],{"class":78},[35,876,877],{"class":82}," wb.Worksheets(",[35,879,141],{"class":45},[35,881,127],{"class":82},[35,883,884,887,890,892,894,896,899,901,903,905,907,909,911,913,915,917,919],{"class":37,"line":92},[35,885,886],{"class":82},"sheet.PrintOut(",[35,888,889],{"class":758},"From",[35,891,118],{"class":78},[35,893,278],{"class":169},[35,895,781],{"class":82},[35,897,898],{"class":758},"To",[35,900,118],{"class":78},[35,902,605],{"class":169},[35,904,781],{"class":82},[35,906,774],{"class":758},[35,908,118],{"class":78},[35,910,605],{"class":169},[35,912,781],{"class":82},[35,914,784],{"class":758},[35,916,118],{"class":78},[35,918,789],{"class":45},[35,920,127],{"class":82},[35,922,923,925,927,930],{"class":37,"line":105},[35,924,362],{"class":169},[35,926,275],{"class":82},[35,928,929],{"class":45},"\"pages in the printout:\"",[35,931,932],{"class":82},", sheet.PageSetup.Pages.Count)\n",[10,934,935,937,938,940,941,944],{},[32,936,889],{}," and ",[32,939,898],{}," are page numbers of the printout, not rows. ",[32,942,943],{},"PageSetup.Pages.Count"," asks Excel how many pages the sheet will produce with its current settings — a quick check that the fit-to-width setup did its job before paper is used.",[387,946,396,951,396,954,396,957,396,960,396,967,396,973,396,978,396,983,396,986,396,990,396,995,396,997,396,999,396,1004,396,1009,396,1017,396,1023,396,1026,396,1029,396,1034,396,1039,396,1044,396,1047,396,1052,396,1058,396,1061,396,1064,396,1069],{"viewBox":947,"role":390,"ariaLabelledBy":948,"xmlns":394,"style":395},"4 0 752 292",[949,950],"pr-seq-t","pr-seq-d",[398,952,953],{"id":949},"What happens when the script prints",[402,955,956],{"id":950},"The Python script starts a private Excel instance, opens the prepared workbook read-only, calls PrintOut with the printer name, Excel renders the pages using the stored page setup and sends the job to the printer spooler, then the script closes the workbook and quits Excel.",[406,958],{"x":408,"y":409,"width":410,"height":959,"fill":412},"292",[406,961],{"x":415,"y":416,"width":962,"height":963,"rx":964,"fill":965,"stroke":966,"style":422},"180.0","48.0","12","#f0f4ff","var(--brand,#5b5cf0)",[435,968,972],{"x":969,"y":970,"style":971},"110.0","44.5","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Python script",[406,974],{"x":975,"y":416,"width":962,"height":963,"rx":964,"fill":976,"stroke":977,"style":422},"290.0","#e7ebef","var(--line,#cdd5e6)",[435,979,982],{"x":980,"y":970,"style":981},"380.0","font-size:13px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Excel (COM)",[406,984],{"x":985,"y":416,"width":962,"height":963,"rx":964,"fill":976,"stroke":977,"style":422},"560.0",[435,987,989],{"x":988,"y":970,"style":981},"650.0","Print spooler",[37,991],{"x1":969,"y1":992,"x2":969,"y2":993,"stroke":977,"style":994},"64.0","276.0","stroke-width:1.5px;stroke-dasharray:5 4",[37,996],{"x1":980,"y1":992,"x2":980,"y2":993,"stroke":977,"style":994},[37,998],{"x1":988,"y1":992,"x2":988,"y2":993,"stroke":977,"style":994},[37,1000],{"x1":1001,"y1":1002,"x2":1003,"y2":1002,"stroke":966,"style":422},"115.0","104.0","371.0",[1005,1006],"polygon",{"points":1007,"fill":1008},"375.0,104.0 366.0,109.0 366.0,99.0","#5b5cf0",[406,1010],{"x":1011,"y":1012,"width":1013,"height":1014,"rx":1015,"fill":412,"stroke":977,"style":1016},"141.3","75.0","207.4","21.0","10","stroke-width:1.2px",[435,1018,1022],{"x":1019,"y":1020,"style":1021},"245.0","89.5","font-size:11.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","1. DispatchEx, Workbooks.Open",[37,1024],{"x1":1001,"y1":1025,"x2":1003,"y2":1025,"stroke":966,"style":422},"152.0",[1005,1027],{"points":1028,"fill":1008},"375.0,152.0 366.0,157.0 366.0,147.0",[406,1030],{"x":1031,"y":1032,"width":1033,"height":1014,"rx":1015,"fill":965,"stroke":966,"style":1016},"150.3","123.0","189.4",[435,1035,1038],{"x":1019,"y":1036,"style":1037},"137.5","font-size:11.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","2. PrintOut(ActivePrinter=…)",[37,1040],{"x1":1041,"y1":1042,"x2":1043,"y2":1042,"stroke":966,"style":422},"385.0","200.0","641.0",[1005,1045],{"points":1046,"fill":1008},"645.0,200.0 636.0,205.0 636.0,195.0",[406,1048],{"x":1049,"y":1050,"width":1051,"height":1014,"rx":1015,"fill":491,"stroke":492,"style":1016},"407.8","171.0","214.3",[435,1053,1057],{"x":1054,"y":1055,"style":1056},"515.0","185.5","font-size:11.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","3. pages using stored page setup",[37,1059],{"x1":1001,"y1":1060,"x2":1003,"y2":1060,"stroke":966,"style":422},"248.0",[1005,1062],{"points":1063,"fill":1008},"375.0,248.0 366.0,253.0 366.0,243.0",[406,1065],{"x":1066,"y":1067,"width":1068,"height":1014,"rx":1015,"fill":412,"stroke":977,"style":1016},"195.9","219.0","98.1",[435,1070,1072],{"x":1019,"y":1071,"style":1021},"233.5","4. Close, Quit",[20,1074,1076],{"id":1075},"step-4-print-a-folder-of-reports-without-dialogs","Step 4 — Print a folder of reports without dialogs",[25,1078,1080],{"className":69,"code":1079,"language":71,"meta":30,"style":30},"from pathlib import Path\n\ndef print_folder(folder, printer, pattern=\"*.xlsx\"):\n    excel = win32.DispatchEx(\"Excel.Application\")\n    excel.Visible = False\n    excel.DisplayAlerts = False\n    printed, failed = [], []\n    try:\n        for path in sorted(Path(folder).glob(pattern)):\n            if path.name.startswith(\"~$\"):\n                continue\n            try:\n                wb = excel.Workbooks.Open(str(path.resolve()), ReadOnly=True, UpdateLinks=0)\n                wb.PrintOut(ActivePrinter=printer)\n                wb.Close(SaveChanges=False)\n                printed.append(path.name)\n            except Exception as exc:                 # keep going; report at the end\n                failed.append((path.name, str(exc)))\n    finally:\n        excel.Quit()\n    return printed, failed\n",[32,1081,1082,1094,1098,1117,1130,1139,1148,1158,1165,1181,1194,1199,1206,1239,1251,1264,1269,1286,1296,1303,1308],{"__ignoreMap":30},[35,1083,1084,1086,1089,1091],{"class":37,"line":38},[35,1085,79],{"class":78},[35,1087,1088],{"class":82}," pathlib ",[35,1090,86],{"class":78},[35,1092,1093],{"class":82}," Path\n",[35,1095,1096],{"class":37,"line":92},[35,1097,109],{"emptyLinePlaceholder":108},[35,1099,1100,1103,1107,1110,1112,1115],{"class":37,"line":105},[35,1101,1102],{"class":78},"def",[35,1104,1106],{"class":1105},"s_Opv"," print_folder",[35,1108,1109],{"class":82},"(folder, printer, pattern",[35,1111,118],{"class":78},[35,1113,1114],{"class":45},"\"*.xlsx\"",[35,1116,289],{"class":82},[35,1118,1119,1122,1124,1126,1128],{"class":37,"line":112},[35,1120,1121],{"class":82},"    excel ",[35,1123,118],{"class":78},[35,1125,708],{"class":82},[35,1127,711],{"class":45},[35,1129,127],{"class":82},[35,1131,1132,1135,1137],{"class":37,"line":130},[35,1133,1134],{"class":82},"    excel.Visible ",[35,1136,118],{"class":78},[35,1138,723],{"class":169},[35,1140,1141,1144,1146],{"class":37,"line":147},[35,1142,1143],{"class":82},"    excel.DisplayAlerts ",[35,1145,118],{"class":78},[35,1147,723],{"class":169},[35,1149,1150,1153,1155],{"class":37,"line":158},[35,1151,1152],{"class":82},"    printed, failed ",[35,1154,118],{"class":78},[35,1156,1157],{"class":82}," [], []\n",[35,1159,1160,1163],{"class":37,"line":173},[35,1161,1162],{"class":78},"    try",[35,1164,740],{"class":82},[35,1166,1167,1170,1173,1175,1178],{"class":37,"line":184},[35,1168,1169],{"class":78},"        for",[35,1171,1172],{"class":82}," path ",[35,1174,269],{"class":78},[35,1176,1177],{"class":169}," sorted",[35,1179,1180],{"class":82},"(Path(folder).glob(pattern)):\n",[35,1182,1183,1186,1189,1192],{"class":37,"line":199},[35,1184,1185],{"class":78},"            if",[35,1187,1188],{"class":82}," path.name.startswith(",[35,1190,1191],{"class":45},"\"~$\"",[35,1193,289],{"class":82},[35,1195,1196],{"class":37,"line":213},[35,1197,1198],{"class":78},"                continue\n",[35,1200,1201,1204],{"class":37,"line":227},[35,1202,1203],{"class":78},"            try",[35,1205,740],{"class":82},[35,1207,1208,1211,1213,1216,1219,1222,1224,1226,1228,1230,1233,1235,1237],{"class":37,"line":260},[35,1209,1210],{"class":82},"                wb ",[35,1212,118],{"class":78},[35,1214,1215],{"class":82}," excel.Workbooks.Open(",[35,1217,1218],{"class":169},"str",[35,1220,1221],{"class":82},"(path.resolve()), ",[35,1223,759],{"class":758},[35,1225,118],{"class":78},[35,1227,764],{"class":169},[35,1229,781],{"class":82},[35,1231,1232],{"class":758},"UpdateLinks",[35,1234,118],{"class":78},[35,1236,409],{"class":169},[35,1238,127],{"class":82},[35,1240,1241,1244,1246,1248],{"class":37,"line":292},[35,1242,1243],{"class":82},"                wb.PrintOut(",[35,1245,784],{"class":758},[35,1247,118],{"class":78},[35,1249,1250],{"class":82},"printer)\n",[35,1252,1253,1256,1258,1260,1262],{"class":37,"line":303},[35,1254,1255],{"class":82},"                wb.Close(",[35,1257,808],{"class":758},[35,1259,118],{"class":78},[35,1261,813],{"class":169},[35,1263,127],{"class":82},[35,1265,1266],{"class":37,"line":314},[35,1267,1268],{"class":82},"                printed.append(path.name)\n",[35,1270,1271,1274,1277,1280,1283],{"class":37,"line":324},[35,1272,1273],{"class":78},"            except",[35,1275,1276],{"class":169}," Exception",[35,1278,1279],{"class":78}," as",[35,1281,1282],{"class":82}," exc:                 ",[35,1284,1285],{"class":195},"# keep going; report at the end\n",[35,1287,1288,1291,1293],{"class":37,"line":335},[35,1289,1290],{"class":82},"                failed.append((path.name, ",[35,1292,1218],{"class":169},[35,1294,1295],{"class":82},"(exc)))\n",[35,1297,1298,1301],{"class":37,"line":340},[35,1299,1300],{"class":78},"    finally",[35,1302,740],{"class":82},[35,1304,1305],{"class":37,"line":359},[35,1306,1307],{"class":82},"        excel.Quit()\n",[35,1309,1310,1313],{"class":37,"line":368},[35,1311,1312],{"class":78},"    return",[35,1314,1315],{"class":82}," printed, failed\n",[10,1317,1318,1319,1322,1323,1326,1327,1330,1331,18],{},"One Excel instance prints every file, which is much faster than starting Excel per file. ",[32,1320,1321],{},"UpdateLinks=0"," stops the \"update external links?\" prompt, ",[32,1324,1325],{},"DisplayAlerts = False"," suppresses most others, and lock files (",[32,1328,1329],{},"~$…",") are skipped. Collecting failures instead of stopping means one corrupt workbook does not block the other forty delivery notes; log them, as in ",[14,1332,1334],{"href":1333},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fhandle-com-errors-and-excel-dialog-prompts-in-python\u002F","Handle COM Errors and Excel Dialog Prompts in Python",[20,1336,1338],{"id":1337},"step-5-proof-print-to-pdf-before-using-paper","Step 5 — Proof-print to PDF before using paper",[10,1340,1341],{},"Before a script prints a hundred copies, render one to PDF and count the pages — the cheapest possible test of the page setup. LibreOffice does it headlessly from the same file, so the check can run in a test on any machine:",[25,1343,1345],{"className":69,"code":1344,"language":71,"meta":30,"style":30},"import subprocess\nfrom pypdf import PdfReader\n\nfor name in (\"deliveries.xlsx\", \"deliveries_print.xlsx\"):\n    subprocess.run([\"soffice\", \"--headless\", \"--convert-to\", \"pdf\", \"--outdir\", \"proof\", name],\n                   check=True, capture_output=True)\n    pages = len(PdfReader(f\"proof\u002F{name.replace('.xlsx', '.pdf')}\").pages)\n    print(f\"{name:24} {pages} pages\")\n",[32,1346,1347,1354,1366,1370,1389,1425,1445,1488],{"__ignoreMap":30},[35,1348,1349,1351],{"class":37,"line":38},[35,1350,86],{"class":78},[35,1352,1353],{"class":82}," subprocess\n",[35,1355,1356,1358,1361,1363],{"class":37,"line":92},[35,1357,79],{"class":78},[35,1359,1360],{"class":82}," pypdf ",[35,1362,86],{"class":78},[35,1364,1365],{"class":82}," PdfReader\n",[35,1367,1368],{"class":37,"line":105},[35,1369,109],{"emptyLinePlaceholder":108},[35,1371,1372,1374,1376,1378,1381,1383,1385,1387],{"class":37,"line":112},[35,1373,263],{"class":78},[35,1375,637],{"class":82},[35,1377,269],{"class":78},[35,1379,1380],{"class":82}," (",[35,1382,124],{"class":45},[35,1384,781],{"class":82},[35,1386,330],{"class":45},[35,1388,289],{"class":82},[35,1390,1391,1394,1397,1399,1402,1404,1407,1409,1412,1414,1417,1419,1422],{"class":37,"line":130},[35,1392,1393],{"class":82},"    subprocess.run([",[35,1395,1396],{"class":45},"\"soffice\"",[35,1398,781],{"class":82},[35,1400,1401],{"class":45},"\"--headless\"",[35,1403,781],{"class":82},[35,1405,1406],{"class":45},"\"--convert-to\"",[35,1408,781],{"class":82},[35,1410,1411],{"class":45},"\"pdf\"",[35,1413,781],{"class":82},[35,1415,1416],{"class":45},"\"--outdir\"",[35,1418,781],{"class":82},[35,1420,1421],{"class":45},"\"proof\"",[35,1423,1424],{"class":82},", name],\n",[35,1426,1427,1430,1432,1434,1436,1439,1441,1443],{"class":37,"line":147},[35,1428,1429],{"class":758},"                   check",[35,1431,118],{"class":78},[35,1433,764],{"class":169},[35,1435,781],{"class":82},[35,1437,1438],{"class":758},"capture_output",[35,1440,118],{"class":78},[35,1442,764],{"class":169},[35,1444,127],{"class":82},[35,1446,1447,1450,1452,1455,1458,1461,1464,1466,1469,1472,1474,1477,1480,1482,1485],{"class":37,"line":158},[35,1448,1449],{"class":82},"    pages ",[35,1451,118],{"class":78},[35,1453,1454],{"class":169}," len",[35,1456,1457],{"class":82},"(PdfReader(",[35,1459,1460],{"class":78},"f",[35,1462,1463],{"class":45},"\"proof\u002F",[35,1465,242],{"class":241},[35,1467,1468],{"class":82},"name.replace(",[35,1470,1471],{"class":45},"'.xlsx'",[35,1473,781],{"class":82},[35,1475,1476],{"class":45},"'.pdf'",[35,1478,1479],{"class":82},")",[35,1481,254],{"class":241},[35,1483,1484],{"class":45},"\"",[35,1486,1487],{"class":82},").pages)\n",[35,1489,1490,1492,1494,1496,1498,1500,1503,1506,1508,1511,1514,1516,1519],{"class":37,"line":173},[35,1491,647],{"class":169},[35,1493,275],{"class":82},[35,1495,1460],{"class":78},[35,1497,1484],{"class":45},[35,1499,242],{"class":241},[35,1501,1502],{"class":82},"name",[35,1504,1505],{"class":78},":24",[35,1507,254],{"class":241},[35,1509,1510],{"class":241}," {",[35,1512,1513],{"class":82},"pages",[35,1515,254],{"class":241},[35,1517,1518],{"class":45}," pages\"",[35,1520,127],{"class":82},[10,1522,1523,1524,1527,1528,18],{},"The unprepared file renders to six pages — the twelve columns do not fit across a portrait page, so every block of rows is printed twice, once for the left columns and once for the right — while the prepared file needs three, with every column on every page and the header repeated. A test that asserts the expected page count catches the day someone adds a sixth column and the printout quietly doubles in length. On Windows, Excel's own ",[32,1525,1526],{},"wb.ExportAsFixedFormat(0, path)"," produces the same proof with Excel's rendering, as in ",[14,1529,1531],{"href":1530},"\u002Fautomating-reporting-workflows\u002Fexporting-excel-reports-to-pdf\u002Fconvert-excel-file-to-pdf-with-python\u002F","Convert an Excel File to PDF with Python",[20,1533,1535],{"id":1534},"step-6-without-excel-libreoffice-or-a-pdf","Step 6 — Without Excel: LibreOffice or a PDF",[10,1537,1538],{},"On servers without Excel, LibreOffice can print directly, using the same page setup stored in the file:",[25,1540,1542],{"className":27,"code":1541,"language":29,"meta":30,"style":30},"soffice --headless --pt \"Warehouse_Laser\" deliveries_print.xlsx\n",[32,1543,1544],{"__ignoreMap":30},[35,1545,1546,1549,1552,1555,1558],{"class":37,"line":38},[35,1547,1548],{"class":41},"soffice",[35,1550,1551],{"class":169}," --headless",[35,1553,1554],{"class":169}," --pt",[35,1556,1557],{"class":45}," \"Warehouse_Laser\"",[35,1559,1560],{"class":45}," deliveries_print.xlsx\n",[10,1562,1563,1566,1567,1570,1571,1575],{},[32,1564,1565],{},"--pt"," prints to the named printer (as the operating system knows it — on Linux, the CUPS queue name) and exits; ",[32,1568,1569],{},"-p"," prints to the default printer. Often the better design is not to print from the server at all: export a PDF and let the printing happen where the printer is — a print server, a shared folder that a printer polls, or the person who needs the paper. PDF export is covered in ",[14,1572,1574],{"href":1573},"\u002Fautomating-reporting-workflows\u002Fexporting-excel-reports-to-pdf\u002Fconvert-excel-to-pdf-on-linux-with-libreoffice\u002F","Convert Excel to PDF on Linux with LibreOffice",", and the PDF can be printed later by any device.",[387,1577,396,1582,396,1585,396,1588,396,1591,396,1596,396,1604,396,1608,396,1612,396,1616,396,1619,396,1622,396,1627,396,1632,396,1637,396,1643,396,1647,396,1652,396,1654,396,1657,396,1661,396,1664,396,1667,396,1673,396,1677,396,1680,396,1682,396,1685,396,1689,396,1692,396,1697,396,1704,396,1708],{"viewBox":1578,"role":390,"ariaLabelledBy":1579,"xmlns":394,"style":395},"4 0 752 272",[1580,1581],"pr-route-t","pr-route-d",[398,1583,1584],{"id":1580},"Choosing how to get the report onto paper",[402,1586,1587],{"id":1581},"On Windows with Excel, print with win32com PrintOut. On a server with LibreOffice and a printer queue, use soffice --pt. Where the printer is elsewhere or printing should be decoupled, export a PDF and print it from a print server or by the recipient.",[406,1589],{"x":408,"y":409,"width":410,"height":1590,"fill":412},"272",[406,1592],{"x":1593,"y":416,"width":1594,"height":1595,"rx":964,"fill":965,"stroke":966,"style":422},"211.8","336.3","75.5",[424,1597,1599],{"transform":1598},"translate(368.0,29.0) scale(1.000)",[428,1600],{"d":1601,"fill":431,"stroke":1602,"style":1603},"M11 4a7 7 0 1 0 .01 0z M16 16l5 5","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[435,1605,1607],{"x":980,"y":1595,"style":1606},"font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","What is available where the script runs?",[37,1609],{"x1":980,"y1":1610,"x2":980,"y2":1611,"stroke":966,"style":422},"91.5","111.5",[37,1613],{"x1":1614,"y1":1611,"x2":1615,"y2":1611,"stroke":966,"style":422},"134.7","625.3",[37,1617],{"x1":1614,"y1":1611,"x2":1614,"y2":1618,"stroke":966,"style":422},"157.5",[1005,1620],{"points":1621,"fill":1008},"134.7,161.5 129.7,152.5 139.7,152.5",[406,1623],{"x":1624,"y":1625,"width":1626,"height":1014,"rx":1015,"fill":412,"stroke":977,"style":1016},"75.1","121.5","119.2",[435,1628,1631],{"x":1614,"y":1629,"style":1630},"136.0","font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","Windows + Excel",[406,1633],{"x":415,"y":1634,"width":1635,"height":1636,"rx":964,"fill":965,"stroke":966,"style":422},"163.5","229.3","93.0",[424,1638,1640],{"transform":1639},"translate(122.7,176.5) scale(1.000)",[428,1641],{"d":1642,"fill":431,"stroke":1602,"style":1603},"M3 5.5l8-1.2v7.2H3z M13 4l8-1.2v8.7h-8z M3 13.5h8v7.2l-8-1.2z M13 13.5h8v8.7l-8-1.2z",[435,1644,1646],{"x":1614,"y":1645,"style":1606},"223.0","win32com PrintOut",[435,1648,1651],{"x":1614,"y":1649,"style":1650},"242.5","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","full control of printer and pages",[37,1653],{"x1":980,"y1":1611,"x2":980,"y2":1618,"stroke":966,"style":422},[1005,1655],{"points":1656,"fill":1008},"380.0,161.5 375.0,152.5 385.0,152.5",[406,1658],{"x":1659,"y":1625,"width":1660,"height":1014,"rx":1015,"fill":412,"stroke":977,"style":1016},"291.0","178.0",[435,1662,1663],{"x":980,"y":1629,"style":1630},"LibreOffice + printer queue",[406,1665],{"x":1666,"y":1634,"width":1635,"height":1636,"rx":964,"fill":491,"stroke":492,"style":422},"265.3",[424,1668,1670],{"transform":1669},"translate(368.0,176.5) scale(1.000)",[428,1671],{"d":1672,"fill":431,"stroke":499,"style":1603},"M4 5h16v14H4z M7 9l3 3-3 3 M12 15h5",[435,1674,1676],{"x":980,"y":1645,"style":1675},"font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","soffice --pt",[435,1678,1679],{"x":980,"y":1649,"style":1650},"uses the stored page setup",[37,1681],{"x1":1615,"y1":1611,"x2":1615,"y2":1618,"stroke":966,"style":422},[1005,1683],{"points":1684,"fill":1008},"625.3,161.5 620.3,152.5 630.3,152.5",[406,1686],{"x":1687,"y":1625,"width":1688,"height":1014,"rx":1015,"fill":412,"stroke":977,"style":1016},"564.2","122.2",[435,1690,1691],{"x":1615,"y":1629,"style":1630},"printer elsewhere",[406,1693],{"x":1694,"y":1634,"width":1635,"height":1636,"rx":964,"fill":1695,"stroke":1696,"style":422},"510.7","#fdefd8","var(--gold,#b4740a)",[424,1698,1700],{"transform":1699},"translate(613.3,176.5) scale(1.000)",[428,1701],{"d":1702,"fill":431,"stroke":1703,"style":1603},"M6 3h9l4 4v14H6z M15 3v4h4 M9 12h6 M9 15.5h6 M9 19h4","var(--gold-ink,#7a4e06)",[435,1705,1707],{"x":1615,"y":1645,"style":1706},"font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Export a PDF",[435,1709,1710],{"x":1615,"y":1649,"style":1650},"print where the paper is needed",[20,1712,1714],{"id":1713},"common-pitfalls","Common pitfalls",[1716,1717,1718,1728,1737,1749,1760,1766],"ul",{},[1719,1720,1721,1725,1726,18],"li",{},[1722,1723,1724],"strong",{},"Printing before fixing the page setup."," Set landscape, fit-to-width and print titles first; check ",[32,1727,943],{},[1719,1729,1730,1733,1734,1736],{},[1722,1731,1732],{},"Relying on the default printer."," Pass ",[32,1735,784],{}," from configuration.",[1719,1738,1739,1742,1743,1745,1746,1748],{},[1722,1740,1741],{},"Orphan Excel processes."," Quit in a ",[32,1744,820],{}," block and use ",[32,1747,839],{}," for a private instance.",[1719,1750,1751,1754,1755,1757,1758,18],{},[1722,1752,1753],{},"Dialogs blocking a scheduled job."," Set ",[32,1756,1325],{}," and open with ",[32,1759,1321],{},[1719,1761,1762,1765],{},[1722,1763,1764],{},"Columns sized too wide."," Fit-to-width scales the whole page down to fit; one overly wide column makes everything tiny, so set sensible widths first.",[1719,1767,1768,1771,1772,1775],{},[1722,1769,1770],{},"Printer names differing between machines."," Network printers may appear as ",[32,1773,1774],{},"\\\\server\\queue","; list the names on the machine that prints.",[20,1777,1779],{"id":1778},"conclusion","Conclusion",[10,1781,1782,1783,1786,1787,1789,1790,1792,1793,937,1795,1797,1798,1800,1801,1803],{},"Prepare the page setup in the workbook — landscape, fit to one page wide, repeated header rows, print area, page numbers — with openpyxl on any platform. On Windows, print through COM: list printers with ",[32,1784,1785],{},"win32print",", open the file read-only in a private Excel instance, call ",[32,1788,861],{}," with ",[32,1791,784],{}," (or on a sheet with ",[32,1794,889],{},[32,1796,898],{},"), and quit in a ",[32,1799,820],{}," block. Without Excel, print with ",[32,1802,1676],{}," or, better, export a PDF and print it where the printer is.",[20,1805,1807],{"id":1806},"frequently-asked-questions","Frequently asked questions",[10,1809,1810,1813],{},[1722,1811,1812],{},"How do I print an Excel file from Python?","\nOn Windows with Excel, open it with win32com through excel.Workbooks.Open and call the workbook's PrintOut method, passing the printer name as ActivePrinter. Without Excel, LibreOffice can print with soffice --headless --pt \"Printer name\" file.xlsx.",[10,1815,1816,1819],{},[1722,1817,1818],{},"How do I choose which printer Python prints to?","\nList the installed printers with win32print.EnumPrinters and pass the chosen name as ActivePrinter to PrintOut. Avoid relying on the default printer for unattended jobs.",[10,1821,1822,1825],{},[1722,1823,1824],{},"How do I make an Excel sheet print on one page wide?","\nSet the sheet's page setup to fit to one page wide and unlimited pages tall. With openpyxl, switch on fitToPage in the sheet properties' page setup section, then set page_setup.fitToWidth to 1 and page_setup.fitToHeight to 0.",[10,1827,1828,1831],{},[1722,1829,1830],{},"How do I print only some pages or one sheet?","\nCall PrintOut on the worksheet object instead of the workbook, and pass From and To with the page numbers, for example sheet.PrintOut(From=1, To=2).",[20,1833,1835],{"id":1834},"related","Related",[1716,1837,1838,1844,1851,1858],{},[1719,1839,1840,1841,1843],{},"Up one level: ",[14,1842,17],{"href":16}," — controlling Excel on Windows.",[1719,1845,1846,1850],{},[14,1847,1849],{"href":1848},"\u002Fautomating-reporting-workflows\u002Fexporting-excel-reports-to-pdf\u002Ffit-an-excel-sheet-to-one-page-in-pdf\u002F","Fit an Excel Sheet to One Page in PDF"," — the same layout problem for PDFs.",[1719,1852,1853,1857],{},[14,1854,1856],{"href":1855},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Finsert-page-breaks-between-groups-with-openpyxl\u002F","Insert Page Breaks Between Groups with openpyxl"," — one group per printed page.",[1719,1859,1860,1864],{},[14,1861,1863],{"href":1862},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Frun-excel-com-automation-from-task-scheduler\u002F","Run Excel COM Automation from Task Scheduler"," — printing on a schedule.",[1866,1867,1868],"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 .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 .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}",{"title":30,"searchDepth":92,"depth":92,"links":1870},[1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881],{"id":22,"depth":92,"text":23},{"id":62,"depth":92,"text":63},{"id":544,"depth":92,"text":545},{"id":668,"depth":92,"text":669},{"id":1075,"depth":92,"text":1076},{"id":1337,"depth":92,"text":1338},{"id":1534,"depth":92,"text":1535},{"id":1713,"depth":92,"text":1714},{"id":1778,"depth":92,"text":1779},{"id":1806,"depth":92,"text":1807},{"id":1834,"depth":92,"text":1835},"2026-10-02","Send workbooks to a printer from a Python script on Windows: prepare the page setup so the printout is right (fit to width, landscape, repeated header rows, print area) with openpyxl or COM, list printers and pick one, call PrintOut for whole workbooks, single sheets or page ranges, print many files in a loop without dialogs, and fall back to LibreOffice or PDF when Excel is not available.","md",[1886,1888,1890,1892],{"q":1812,"a":1887},"On Windows with Excel, open it with win32com through excel.Workbooks.Open and call the workbook's PrintOut method, passing the printer name as ActivePrinter. Without Excel, LibreOffice can print with soffice --headless --pt \"Printer name\" file.xlsx.",{"q":1818,"a":1889},"List the installed printers with win32print.EnumPrinters and pass the chosen name as ActivePrinter to PrintOut. Avoid relying on the default printer for unattended jobs.",{"q":1824,"a":1891},"Set the sheet's page setup to fit to one page wide and unlimited pages tall. With openpyxl, switch on fitToPage in the sheet properties' page setup section, then set page_setup.fitToWidth to 1 and page_setup.fitToHeight to 0.",{"q":1830,"a":1893},"Call PrintOut on the worksheet object instead of the workbook, and pass From and To with the page numbers, for example sheet.PrintOut(From=1, To=2).","print an excel workbook from python with win32com",null,{"breadcrumb":1897},[1898,1901,1904],{"name":1899,"item":1900},"Home","\u002F",{"name":1902,"item":1903},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":17,"item":16},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fprint-an-excel-workbook-from-python-with-win32com",{"title":1907,"description":1908},"Print Excel Workbooks from Python with win32com (Windows)","Print Excel files from Python: page setup for one-page-wide landscape printouts, win32print to list printers, Workbook.PrintOut with ActivePrinter, From\u002FTo and Copies, printing a folder of reports without dialogs, and LibreOffice or PDF alternatives.","print-an-excel-workbook-from-python-with-win32com","getting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fprint-an-excel-workbook-from-python-with-win32com\u002Findex",[1912,1913],"com-automation","pdf-export","how-to","Lbu9_ysTRjJQHvMiDPPRvfUmQDX-0fNRbViTKKAkSEE",[1917,1920],{"title":1334,"path":1918,"stem":1919,"children":-1},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fhandle-com-errors-and-excel-dialog-prompts-in-python","getting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fhandle-com-errors-and-excel-dialog-prompts-in-python\u002Findex",{"title":1921,"path":1922,"stem":1923,"children":-1},"Read and Write Cell Ranges with win32com","\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fread-and-write-cell-ranges-with-win32com","getting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fread-and-write-cell-ranges-with-win32com\u002Findex",[1925,1927],{"path":1926,"title":17},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32",{"path":1928,"title":1902},"\u002Fgetting-started-with-python-excel-automation",[],[1931,1934,1937,1940,1942,1944],{"path":1932,"title":1933,"kind":1914},"\u002Fautomating-reporting-workflows\u002Ftesting-and-packaging-excel-automation-scripts\u002Ftest-win32com-and-xlwings-code-without-excel","Test win32com and xlwings Code Without Excel",{"path":1935,"title":1936,"kind":1914},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fexport-an-excel-chart-as-an-image","Export an Excel Chart as an Image with Python",{"path":1938,"title":1939,"kind":1914},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fautomate-excel-on-macos-with-python","Automate Excel on macOS with Python",{"path":1941,"title":855,"kind":1914},"\u002Fgetting-started-with-python-excel-automation\u002Fautomating-excel-with-com-and-pywin32\u002Fclose-excel-cleanly-and-avoid-orphan-com-processes",{"path":1918,"title":1334,"kind":1943},"fix",{"path":1922,"title":1921,"kind":1914},1790972055444]