[{"data":1,"prerenderedAt":2607},["ShallowReactive",2],{"doc:\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fprint-mailing-labels-from-an-excel-address-list":3,"surround:\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fprint-mailing-labels-from-an-excel-address-list":2571,"ancestors:\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fprint-mailing-labels-from-an-excel-address-list":2580,"children:\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fprint-mailing-labels-from-an-excel-address-list":2585,"related:\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fprint-mailing-labels-from-an-excel-address-list":2586},{"id":4,"title":5,"body":6,"dateModified":2538,"datePublished":2538,"description":2539,"extension":2540,"faq":2541,"keyword":2550,"kind":2551,"meta":2552,"navigation":135,"path":2560,"seo":2561,"slug":2564,"stem":2565,"topics":2566,"type":2569,"__hash__":2570},"docs\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fprint-mailing-labels-from-an-excel-address-list\u002Findex.md","Print Mailing Labels from an Excel Address List",{"type":7,"value":8,"toc":2525},"minimark",[9,24,29,63,69,73,81,633,640,816,820,823,1119,1134,1138,1141,1611,1617,1805,1809,1819,1867,1879,2009,2013,2016,2369,2375,2379,2415,2419,2453,2457,2460,2464,2470,2476,2482,2488,2492,2521],[10,11,12,13,17,18,23],"p",{},"Word's mail merge will print labels from a spreadsheet, but it is a manual, click-through job that nobody wants to repeat every month — and it falls over on the details: empty \"Address 2\" cells leave gaps, long company names spill past the label edge, and a half-used sheet of labels gets wasted. A short Python script reads the address list with pandas and draws the labels with ",[14,15,16],"code",{},"reportlab",", positioned to the millimetre for the label stock in the printer. This page describes a label sheet by its measurements, cleans each address into tidy lines, shrinks text that would overflow, starts printing part-way down a used sheet, and adds an alignment test and a placement check. It belongs to ",[19,20,22],"a",{"href":21},"\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002F","Generating Excel Reports from Templates",".",[25,26,28],"h2",{"id":27},"prerequisites","Prerequisites",[30,31,36],"pre",{"className":32,"code":33,"language":34,"meta":35,"style":35},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl reportlab pypdf\n","bash","",[14,37,38],{"__ignoreMap":35},[39,40,43,47,51,54,57,60],"span",{"class":41,"line":42},"line",1,[39,44,46],{"class":45},"sMTad","pip",[39,48,50],{"class":49},"srMev"," install",[39,52,53],{"class":49}," pandas",[39,55,56],{"class":49}," openpyxl",[39,58,59],{"class":49}," reportlab",[39,61,62],{"class":49}," pypdf\n",[10,64,65,68],{},[14,66,67],{},"addresses.xlsx"," holds seven contacts with name, optional company, two address lines, city, postcode and country — with the usual gaps: no company for some, no second address line for most. The labels are sent from the United Kingdom, so the home country is left off UK addresses.",[25,70,72],{"id":71},"step-1-describe-the-label-sheet","Step 1 — Describe the label sheet",[10,74,75,76,80],{},"Every label product is a grid defined by a handful of measurements printed on the box or the manufacturer's template: page size, label size, the number of columns and rows, the top and left margins, and the ",[77,78,79],"em",{},"pitch"," — the distance from the start of one label to the start of the next, which includes any gap:",[30,82,86],{"className":83,"code":84,"language":85,"meta":35,"style":35},"language-python shiki shiki-themes github-light github-dark-high-contrast","from dataclasses import dataclass\nfrom reportlab.lib.pagesizes import A4, letter\nfrom reportlab.lib.units import inch, mm\n\n@dataclass(frozen=True)\nclass LabelSheet:\n    page: tuple\n    cols: int\n    rows: int\n    width: float\n    height: float\n    left: float\n    top: float\n    h_pitch: float\n    v_pitch: float\n\n    def origin(self, index):\n        \"\"\"Bottom-left corner of label number `index` (0-based, row by row).\"\"\"\n        col, row = index % self.cols, index \u002F\u002F self.cols\n        x = self.left + col * self.h_pitch\n        y = self.page[1] - self.top - row * self.v_pitch - self.height\n        return x, y\n\nL7160 = LabelSheet(A4, cols=3, rows=7, width=63.5 * mm, height=38.1 * mm,\n                   left=7.2 * mm, top=15.1 * mm, h_pitch=66.0 * mm, v_pitch=38.1 * mm)\nAVERY_5160 = LabelSheet(letter, cols=3, rows=10, width=2.625 * inch, height=1 * inch,\n                        left=0.1875 * inch, top=0.5 * inch, h_pitch=2.75 * inch, v_pitch=1 * inch)\nprint(\"L7160:\", L7160.cols * L7160.rows, \"labels per sheet; 5160:\", AVERY_5160.cols * AVERY_5160.rows)\n","python",[14,87,88,104,117,130,137,161,173,182,191,199,208,216,224,232,240,248,253,265,271,299,326,372,381,386,445,496,548,596],{"__ignoreMap":35},[39,89,90,94,98,101],{"class":41,"line":42},[39,91,93],{"class":92},"s-kum","from",[39,95,97],{"class":96},"skGVy"," dataclasses ",[39,99,100],{"class":92},"import",[39,102,103],{"class":96}," dataclass\n",[39,105,107,109,112,114],{"class":41,"line":106},2,[39,108,93],{"class":92},[39,110,111],{"class":96}," reportlab.lib.pagesizes ",[39,113,100],{"class":92},[39,115,116],{"class":96}," A4, letter\n",[39,118,120,122,125,127],{"class":41,"line":119},3,[39,121,93],{"class":92},[39,123,124],{"class":96}," reportlab.lib.units ",[39,126,100],{"class":92},[39,128,129],{"class":96}," inch, mm\n",[39,131,133],{"class":41,"line":132},4,[39,134,136],{"emptyLinePlaceholder":135},true,"\n",[39,138,140,144,147,151,154,158],{"class":41,"line":139},5,[39,141,143],{"class":142},"s_Opv","@dataclass",[39,145,146],{"class":96},"(",[39,148,150],{"class":149},"sa561","frozen",[39,152,153],{"class":92},"=",[39,155,157],{"class":156},"sP0c6","True",[39,159,160],{"class":96},")\n",[39,162,164,167,170],{"class":41,"line":163},6,[39,165,166],{"class":92},"class",[39,168,169],{"class":45}," LabelSheet",[39,171,172],{"class":96},":\n",[39,174,176,179],{"class":41,"line":175},7,[39,177,178],{"class":96},"    page: ",[39,180,181],{"class":156},"tuple\n",[39,183,185,188],{"class":41,"line":184},8,[39,186,187],{"class":96},"    cols: ",[39,189,190],{"class":156},"int\n",[39,192,194,197],{"class":41,"line":193},9,[39,195,196],{"class":96},"    rows: ",[39,198,190],{"class":156},[39,200,202,205],{"class":41,"line":201},10,[39,203,204],{"class":96},"    width: ",[39,206,207],{"class":156},"float\n",[39,209,211,214],{"class":41,"line":210},11,[39,212,213],{"class":96},"    height: ",[39,215,207],{"class":156},[39,217,219,222],{"class":41,"line":218},12,[39,220,221],{"class":96},"    left: ",[39,223,207],{"class":156},[39,225,227,230],{"class":41,"line":226},13,[39,228,229],{"class":96},"    top: ",[39,231,207],{"class":156},[39,233,235,238],{"class":41,"line":234},14,[39,236,237],{"class":96},"    h_pitch: ",[39,239,207],{"class":156},[39,241,243,246],{"class":41,"line":242},15,[39,244,245],{"class":96},"    v_pitch: ",[39,247,207],{"class":156},[39,249,251],{"class":41,"line":250},16,[39,252,136],{"emptyLinePlaceholder":135},[39,254,256,259,262],{"class":41,"line":255},17,[39,257,258],{"class":92},"    def",[39,260,261],{"class":142}," origin",[39,263,264],{"class":96},"(self, index):\n",[39,266,268],{"class":41,"line":267},18,[39,269,270],{"class":49},"        \"\"\"Bottom-left corner of label number `index` (0-based, row by row).\"\"\"\n",[39,272,274,277,279,282,285,288,291,294,296],{"class":41,"line":273},19,[39,275,276],{"class":96},"        col, row ",[39,278,153],{"class":92},[39,280,281],{"class":96}," index ",[39,283,284],{"class":92},"%",[39,286,287],{"class":156}," self",[39,289,290],{"class":96},".cols, index ",[39,292,293],{"class":92},"\u002F\u002F",[39,295,287],{"class":156},[39,297,298],{"class":96},".cols\n",[39,300,302,305,307,309,312,315,318,321,323],{"class":41,"line":301},20,[39,303,304],{"class":96},"        x ",[39,306,153],{"class":92},[39,308,287],{"class":156},[39,310,311],{"class":96},".left ",[39,313,314],{"class":92},"+",[39,316,317],{"class":96}," col ",[39,319,320],{"class":92},"*",[39,322,287],{"class":156},[39,324,325],{"class":96},".h_pitch\n",[39,327,329,332,334,336,339,342,345,348,350,353,355,358,360,362,365,367,369],{"class":41,"line":328},21,[39,330,331],{"class":96},"        y ",[39,333,153],{"class":92},[39,335,287],{"class":156},[39,337,338],{"class":96},".page[",[39,340,341],{"class":156},"1",[39,343,344],{"class":96},"] ",[39,346,347],{"class":92},"-",[39,349,287],{"class":156},[39,351,352],{"class":96},".top ",[39,354,347],{"class":92},[39,356,357],{"class":96}," row ",[39,359,320],{"class":92},[39,361,287],{"class":156},[39,363,364],{"class":96},".v_pitch ",[39,366,347],{"class":92},[39,368,287],{"class":156},[39,370,371],{"class":96},".height\n",[39,373,375,378],{"class":41,"line":374},22,[39,376,377],{"class":92},"        return",[39,379,380],{"class":96}," x, y\n",[39,382,384],{"class":41,"line":383},23,[39,385,136],{"emptyLinePlaceholder":135},[39,387,389,392,394,397,400,402,405,408,411,413,416,418,421,423,426,429,432,435,437,440,442],{"class":41,"line":388},24,[39,390,391],{"class":96},"L7160 ",[39,393,153],{"class":92},[39,395,396],{"class":96}," LabelSheet(A4, ",[39,398,399],{"class":149},"cols",[39,401,153],{"class":92},[39,403,404],{"class":156},"3",[39,406,407],{"class":96},", ",[39,409,410],{"class":149},"rows",[39,412,153],{"class":92},[39,414,415],{"class":156},"7",[39,417,407],{"class":96},[39,419,420],{"class":149},"width",[39,422,153],{"class":92},[39,424,425],{"class":156},"63.5",[39,427,428],{"class":92}," *",[39,430,431],{"class":96}," mm, ",[39,433,434],{"class":149},"height",[39,436,153],{"class":92},[39,438,439],{"class":156},"38.1",[39,441,428],{"class":92},[39,443,444],{"class":96}," mm,\n",[39,446,448,451,453,456,458,460,463,465,468,470,472,475,477,480,482,484,487,489,491,493],{"class":41,"line":447},25,[39,449,450],{"class":149},"                   left",[39,452,153],{"class":92},[39,454,455],{"class":156},"7.2",[39,457,428],{"class":92},[39,459,431],{"class":96},[39,461,462],{"class":149},"top",[39,464,153],{"class":92},[39,466,467],{"class":156},"15.1",[39,469,428],{"class":92},[39,471,431],{"class":96},[39,473,474],{"class":149},"h_pitch",[39,476,153],{"class":92},[39,478,479],{"class":156},"66.0",[39,481,428],{"class":92},[39,483,431],{"class":96},[39,485,486],{"class":149},"v_pitch",[39,488,153],{"class":92},[39,490,439],{"class":156},[39,492,428],{"class":92},[39,494,495],{"class":96}," mm)\n",[39,497,499,502,505,508,510,512,514,516,518,520,523,525,527,529,532,534,537,539,541,543,545],{"class":41,"line":498},26,[39,500,501],{"class":156},"AVERY_5160",[39,503,504],{"class":92}," =",[39,506,507],{"class":96}," LabelSheet(letter, ",[39,509,399],{"class":149},[39,511,153],{"class":92},[39,513,404],{"class":156},[39,515,407],{"class":96},[39,517,410],{"class":149},[39,519,153],{"class":92},[39,521,522],{"class":156},"10",[39,524,407],{"class":96},[39,526,420],{"class":149},[39,528,153],{"class":92},[39,530,531],{"class":156},"2.625",[39,533,428],{"class":92},[39,535,536],{"class":96}," inch, ",[39,538,434],{"class":149},[39,540,153],{"class":92},[39,542,341],{"class":156},[39,544,428],{"class":92},[39,546,547],{"class":96}," inch,\n",[39,549,551,554,556,559,561,563,565,567,570,572,574,576,578,581,583,585,587,589,591,593],{"class":41,"line":550},27,[39,552,553],{"class":149},"                        left",[39,555,153],{"class":92},[39,557,558],{"class":156},"0.1875",[39,560,428],{"class":92},[39,562,536],{"class":96},[39,564,462],{"class":149},[39,566,153],{"class":92},[39,568,569],{"class":156},"0.5",[39,571,428],{"class":92},[39,573,536],{"class":96},[39,575,474],{"class":149},[39,577,153],{"class":92},[39,579,580],{"class":156},"2.75",[39,582,428],{"class":92},[39,584,536],{"class":96},[39,586,486],{"class":149},[39,588,153],{"class":92},[39,590,341],{"class":156},[39,592,428],{"class":92},[39,594,595],{"class":96}," inch)\n",[39,597,599,602,604,607,610,612,615,618,620,622,625,627,630],{"class":41,"line":598},28,[39,600,601],{"class":156},"print",[39,603,146],{"class":96},[39,605,606],{"class":49},"\"L7160:\"",[39,608,609],{"class":96},", L7160.cols ",[39,611,320],{"class":92},[39,613,614],{"class":96}," L7160.rows, ",[39,616,617],{"class":49},"\"labels per sheet; 5160:\"",[39,619,407],{"class":96},[39,621,501],{"class":156},[39,623,624],{"class":96},".cols ",[39,626,320],{"class":92},[39,628,629],{"class":156}," AVERY_5160",[39,631,632],{"class":96},".rows)\n",[10,634,635,636,639],{},"The two definitions cover the most common stock: Avery L7160 (21 labels on A4, used across Europe) and Avery 5160 (30 labels on US Letter). reportlab measures from the bottom-left corner of the page, while label templates measure from the top, so ",[14,637,638],{},"origin()"," converts. For any other product, copy its five or six numbers from the template; the rest of the code does not change.",[641,642,650,651,650,655,650,659,650,667,650,676,650,680,650,687,650,691,650,695,650,699,650,703,650,707,650,711,650,714,650,718,650,720,650,723,650,727,650,731,650,734,650,738,650,740,650,743,650,745,650,748,650,750,650,753,650,756,650,759,650,761,650,764,650,766,650,769,650,771,650,774,650,777,650,781,650,783,650,787,650,789,650,791,650,793,650,796,650,799,650,803,650,805,650,808,650,810,650,812,650,814],"svg",{"viewBox":643,"role":644,"ariaLabelledBy":645,"xmlns":648,"style":649},"190 0 379 196","img",[646,647],"ml-grid-t","ml-grid-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:379px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[652,653,654],"title",{"id":646},"An L7160 sheet as a grid of labels",[656,657,658],"desc",{"id":647},"Seven rows of three labels on an A4 page. Labels are filled row by row starting at the top left, so label 0 is top left, label 2 top right and label 3 starts the second row. The first two labels are marked as already used.",[660,661],"rect",{"x":662,"y":663,"width":664,"height":665,"fill":666},"190","0","379","196","#ffffff",[660,668],{"x":669,"y":670,"width":671,"height":672,"rx":663,"fill":673,"stroke":674,"style":675},"206.9","16.0","32.0","24.0","#e7ebef","var(--line,#cdd5e6)","stroke-width:1px",[660,677],{"x":678,"y":670,"width":679,"height":672,"rx":663,"fill":673,"stroke":674,"style":675},"238.9","112.2",[681,682,686],"text",{"x":683,"y":684,"style":685},"294.9","33.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[660,688],{"x":689,"y":670,"width":690,"height":672,"rx":663,"fill":673,"stroke":674,"style":675},"351.0","111.1",[681,692,694],{"x":693,"y":684,"style":685},"406.6","B",[660,696],{"x":697,"y":670,"width":698,"height":672,"rx":663,"fill":673,"stroke":674,"style":675},"462.1","91.0",[681,700,702],{"x":701,"y":684,"style":685},"507.6","C",[660,704],{"x":669,"y":705,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"40.0","28.0",[681,708,341],{"x":709,"y":710,"style":685},"222.9","59.0",[660,712],{"x":678,"y":705,"width":679,"height":706,"rx":663,"fill":673,"stroke":674,"style":713},"stroke-width:1.5px",[681,715,717],{"x":683,"y":710,"style":716},"font-size:10.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","0 · used",[660,719],{"x":689,"y":705,"width":690,"height":706,"rx":663,"fill":673,"stroke":674,"style":713},[681,721,722],{"x":693,"y":710,"style":716},"1 · used",[660,724],{"x":697,"y":705,"width":698,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},"#d9f4f1","var(--teal,#0f9488)",[681,728,730],{"x":701,"y":710,"style":729},"font-size:10.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","2 · Ana Ruiz",[660,732],{"x":669,"y":733,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"68.0",[681,735,737],{"x":709,"y":736,"style":685},"87.0","2",[660,739],{"x":678,"y":733,"width":679,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},[681,741,742],{"x":683,"y":736,"style":729},"3 · Ben Okafor",[660,744],{"x":689,"y":733,"width":690,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},[681,746,747],{"x":693,"y":736,"style":729},"4 · Chloé Martin",[660,749],{"x":697,"y":733,"width":698,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},[681,751,752],{"x":701,"y":736,"style":729},"5 · Dev Patel",[660,754],{"x":669,"y":755,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"96.0",[681,757,404],{"x":709,"y":758,"style":685},"115.0",[660,760],{"x":678,"y":755,"width":679,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},[681,762,763],{"x":683,"y":758,"style":729},"6 · Eva Lindqvist",[660,765],{"x":689,"y":755,"width":690,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},[681,767,768],{"x":693,"y":758,"style":729},"7 · Farid Haddad",[660,770],{"x":697,"y":755,"width":698,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},[681,772,773],{"x":701,"y":758,"style":729},"8 · Grace Liu",[660,775],{"x":669,"y":776,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"124.0",[681,778,780],{"x":709,"y":779,"style":685},"143.0","4",[660,782],{"x":678,"y":776,"width":679,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,784,786],{"x":683,"y":779,"style":785},"font-size:10.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","9",[660,788],{"x":689,"y":776,"width":690,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,790,522],{"x":693,"y":779,"style":785},[660,792],{"x":697,"y":776,"width":698,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,794,795],{"x":701,"y":779,"style":785},"11",[660,797],{"x":669,"y":798,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"152.0",[681,800,802],{"x":709,"y":801,"style":685},"171.0","5",[660,804],{"x":678,"y":798,"width":679,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,806,807],{"x":683,"y":801,"style":785},"…",[660,809],{"x":689,"y":798,"width":690,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,811,807],{"x":693,"y":801,"style":785},[660,813],{"x":697,"y":798,"width":698,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,815,807],{"x":701,"y":801,"style":785},[25,817,819],{"id":818},"step-2-turn-each-row-into-address-lines","Step 2 — Turn each row into address lines",[10,821,822],{},"A label should show only the lines that have content, in postal order. Building the lines in a function keeps that logic in one place:",[30,824,826],{"className":83,"code":825,"language":85,"meta":35,"style":35},"import pandas as pd\n\nHOME = \"United Kingdom\"\n\ndef address_lines(row):\n    lines = [row[\"Name\"], row[\"Company\"], row[\"Address 1\"], row[\"Address 2\"]]\n    if row[\"Country\"] == HOME:\n        lines += [row[\"City\"].upper(), row[\"Postcode\"]]\n    else:\n        lines += [f'{row[\"Postcode\"]} {row[\"City\"]}'.strip(), row[\"Country\"].upper()]\n    return [str(v).strip() for v in lines if pd.notna(v) and str(v).strip()]\n\npeople = pd.read_excel(\"addresses.xlsx\", dtype=str)\nlabels = [address_lines(r) for _, r in people.iterrows()]\nfor lines in labels[:3]:\n    print(\" \u002F \".join(lines))\n",[14,827,828,841,845,855,859,870,902,923,944,951,1002,1042,1046,1070,1090,1106],{"__ignoreMap":35},[39,829,830,832,835,838],{"class":41,"line":42},[39,831,100],{"class":92},[39,833,834],{"class":96}," pandas ",[39,836,837],{"class":92},"as",[39,839,840],{"class":96}," pd\n",[39,842,843],{"class":41,"line":106},[39,844,136],{"emptyLinePlaceholder":135},[39,846,847,850,852],{"class":41,"line":119},[39,848,849],{"class":156},"HOME",[39,851,504],{"class":92},[39,853,854],{"class":49}," \"United Kingdom\"\n",[39,856,857],{"class":41,"line":132},[39,858,136],{"emptyLinePlaceholder":135},[39,860,861,864,867],{"class":41,"line":139},[39,862,863],{"class":92},"def",[39,865,866],{"class":142}," address_lines",[39,868,869],{"class":96},"(row):\n",[39,871,872,875,877,880,883,886,889,891,894,896,899],{"class":41,"line":163},[39,873,874],{"class":96},"    lines ",[39,876,153],{"class":92},[39,878,879],{"class":96}," [row[",[39,881,882],{"class":49},"\"Name\"",[39,884,885],{"class":96},"], row[",[39,887,888],{"class":49},"\"Company\"",[39,890,885],{"class":96},[39,892,893],{"class":49},"\"Address 1\"",[39,895,885],{"class":96},[39,897,898],{"class":49},"\"Address 2\"",[39,900,901],{"class":96},"]]\n",[39,903,904,907,910,913,915,918,921],{"class":41,"line":175},[39,905,906],{"class":92},"    if",[39,908,909],{"class":96}," row[",[39,911,912],{"class":49},"\"Country\"",[39,914,344],{"class":96},[39,916,917],{"class":92},"==",[39,919,920],{"class":156}," HOME",[39,922,172],{"class":96},[39,924,925,928,931,933,936,939,942],{"class":41,"line":184},[39,926,927],{"class":96},"        lines ",[39,929,930],{"class":92},"+=",[39,932,879],{"class":96},[39,934,935],{"class":49},"\"City\"",[39,937,938],{"class":96},"].upper(), row[",[39,940,941],{"class":49},"\"Postcode\"",[39,943,901],{"class":96},[39,945,946,949],{"class":41,"line":193},[39,947,948],{"class":92},"    else",[39,950,172],{"class":96},[39,952,953,955,957,960,963,966,970,973,975,978,981,984,986,988,990,992,994,997,999],{"class":41,"line":201},[39,954,927],{"class":96},[39,956,930],{"class":92},[39,958,959],{"class":96}," [",[39,961,962],{"class":92},"f",[39,964,965],{"class":49},"'",[39,967,969],{"class":968},"sSjpA","{",[39,971,972],{"class":96},"row[",[39,974,941],{"class":49},[39,976,977],{"class":96},"]",[39,979,980],{"class":968},"}",[39,982,983],{"class":968}," {",[39,985,972],{"class":96},[39,987,935],{"class":49},[39,989,977],{"class":96},[39,991,980],{"class":968},[39,993,965],{"class":49},[39,995,996],{"class":96},".strip(), row[",[39,998,912],{"class":49},[39,1000,1001],{"class":96},"].upper()]\n",[39,1003,1004,1007,1009,1012,1015,1018,1021,1024,1027,1030,1033,1036,1039],{"class":41,"line":210},[39,1005,1006],{"class":92},"    return",[39,1008,959],{"class":96},[39,1010,1011],{"class":156},"str",[39,1013,1014],{"class":96},"(v).strip() ",[39,1016,1017],{"class":92},"for",[39,1019,1020],{"class":96}," v ",[39,1022,1023],{"class":92},"in",[39,1025,1026],{"class":96}," lines ",[39,1028,1029],{"class":92},"if",[39,1031,1032],{"class":96}," pd.notna(v) ",[39,1034,1035],{"class":92},"and",[39,1037,1038],{"class":156}," str",[39,1040,1041],{"class":96},"(v).strip()]\n",[39,1043,1044],{"class":41,"line":218},[39,1045,136],{"emptyLinePlaceholder":135},[39,1047,1048,1051,1053,1056,1059,1061,1064,1066,1068],{"class":41,"line":226},[39,1049,1050],{"class":96},"people ",[39,1052,153],{"class":92},[39,1054,1055],{"class":96}," pd.read_excel(",[39,1057,1058],{"class":49},"\"addresses.xlsx\"",[39,1060,407],{"class":96},[39,1062,1063],{"class":149},"dtype",[39,1065,153],{"class":92},[39,1067,1011],{"class":156},[39,1069,160],{"class":96},[39,1071,1072,1075,1077,1080,1082,1085,1087],{"class":41,"line":234},[39,1073,1074],{"class":96},"labels ",[39,1076,153],{"class":92},[39,1078,1079],{"class":96}," [address_lines(r) ",[39,1081,1017],{"class":92},[39,1083,1084],{"class":96}," _, r ",[39,1086,1023],{"class":92},[39,1088,1089],{"class":96}," people.iterrows()]\n",[39,1091,1092,1094,1096,1098,1101,1103],{"class":41,"line":242},[39,1093,1017],{"class":92},[39,1095,1026],{"class":96},[39,1097,1023],{"class":92},[39,1099,1100],{"class":96}," labels[:",[39,1102,404],{"class":156},[39,1104,1105],{"class":96},"]:\n",[39,1107,1108,1111,1113,1116],{"class":41,"line":250},[39,1109,1110],{"class":156},"    print",[39,1112,146],{"class":96},[39,1114,1115],{"class":49},"\" \u002F \"",[39,1117,1118],{"class":96},".join(lines))\n",[10,1120,1121,1122,1125,1126,1129,1130,23],{},"Reading with ",[14,1123,1124],{},"dtype=str"," keeps postcodes such as \"69002\" and \"753 20\" as text instead of numbers. Empty cells arrive as ",[14,1127,1128],{},"NaN"," and are dropped together with whitespace-only values, so a missing company or second address line leaves no gap. UK addresses end with the town in capitals and the postcode on its own line; foreign ones end with the postcode and city followed by the country in capitals, the usual convention for international post. Adapt the rule to your own country's postal guidance — this is the part most worth reviewing with whoever posts the letters. Columns with stray spaces or inconsistent capitals are easier to fix in pandas before this step, as in ",[19,1131,1133],{"href":1132},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fstrip-whitespace-and-normalise-text-columns-with-pandas\u002F","Strip Whitespace and Normalise Text Columns with pandas",[25,1135,1137],{"id":1136},"step-3-draw-the-labels-shrinking-long-lines","Step 3 — Draw the labels, shrinking long lines",[10,1139,1140],{},"Each label is drawn at its origin with a small inner padding. A line too long for the label gets a smaller font, down to a minimum, rather than running off the edge:",[30,1142,1144],{"className":83,"code":1143,"language":85,"meta":35,"style":35},"from reportlab.pdfbase.pdfmetrics import stringWidth\nfrom reportlab.pdfgen import canvas\n\nFONT, SIZE, MIN_SIZE, PAD = \"Helvetica\", 10, 7, 4 * mm\n\ndef fit_size(text, max_width):\n    size = SIZE\n    while size > MIN_SIZE and stringWidth(text, FONT, size) > max_width:\n        size -= 0.5\n    return size\n\ndef draw_labels(path, sheet, labels, skip=0, outline=False):\n    c = canvas.Canvas(path, pagesize=sheet.page)\n    per_page = sheet.cols * sheet.rows\n    for n, lines in enumerate(labels, start=skip):\n        if n and n % per_page == 0:\n            c.showPage()\n        x, y = sheet.origin(n % per_page)\n        if outline:\n            c.setDash(2, 2)\n            c.rect(x, y, sheet.width, sheet.height)\n            c.setDash()\n        line_h = SIZE * 1.2\n        text_y = y + (sheet.height + len(lines) * line_h) \u002F 2 - SIZE    # centre the block vertically\n        for line in lines:\n            c.setFont(FONT, fit_size(line, sheet.width - 2 * PAD))\n            c.drawString(x + PAD, text_y, line)\n            text_y -= line_h\n    c.save()\n\ndraw_labels(\"labels.pdf\", L7160, labels, skip=2)\nprint(\"labels.pdf written; first label drawn in position\", 2)\n",[14,1145,1146,1158,1170,1174,1216,1220,1230,1240,1270,1281,1288,1292,1317,1335,1350,1374,1398,1403,1418,1425,1438,1443,1448,1463,1506,1519,1541,1553,1563,1569,1574,1595],{"__ignoreMap":35},[39,1147,1148,1150,1153,1155],{"class":41,"line":42},[39,1149,93],{"class":92},[39,1151,1152],{"class":96}," reportlab.pdfbase.pdfmetrics ",[39,1154,100],{"class":92},[39,1156,1157],{"class":96}," stringWidth\n",[39,1159,1160,1162,1165,1167],{"class":41,"line":106},[39,1161,93],{"class":92},[39,1163,1164],{"class":96}," reportlab.pdfgen ",[39,1166,100],{"class":92},[39,1168,1169],{"class":96}," canvas\n",[39,1171,1172],{"class":41,"line":119},[39,1173,136],{"emptyLinePlaceholder":135},[39,1175,1176,1179,1181,1184,1186,1189,1191,1194,1196,1199,1201,1203,1205,1207,1209,1211,1213],{"class":41,"line":132},[39,1177,1178],{"class":156},"FONT",[39,1180,407],{"class":96},[39,1182,1183],{"class":156},"SIZE",[39,1185,407],{"class":96},[39,1187,1188],{"class":156},"MIN_SIZE",[39,1190,407],{"class":96},[39,1192,1193],{"class":156},"PAD",[39,1195,504],{"class":92},[39,1197,1198],{"class":49}," \"Helvetica\"",[39,1200,407],{"class":96},[39,1202,522],{"class":156},[39,1204,407],{"class":96},[39,1206,415],{"class":156},[39,1208,407],{"class":96},[39,1210,780],{"class":156},[39,1212,428],{"class":92},[39,1214,1215],{"class":96}," mm\n",[39,1217,1218],{"class":41,"line":139},[39,1219,136],{"emptyLinePlaceholder":135},[39,1221,1222,1224,1227],{"class":41,"line":163},[39,1223,863],{"class":92},[39,1225,1226],{"class":142}," fit_size",[39,1228,1229],{"class":96},"(text, max_width):\n",[39,1231,1232,1235,1237],{"class":41,"line":175},[39,1233,1234],{"class":96},"    size ",[39,1236,153],{"class":92},[39,1238,1239],{"class":156}," SIZE\n",[39,1241,1242,1245,1248,1251,1254,1257,1260,1262,1265,1267],{"class":41,"line":184},[39,1243,1244],{"class":92},"    while",[39,1246,1247],{"class":96}," size ",[39,1249,1250],{"class":92},">",[39,1252,1253],{"class":156}," MIN_SIZE",[39,1255,1256],{"class":92}," and",[39,1258,1259],{"class":96}," stringWidth(text, ",[39,1261,1178],{"class":156},[39,1263,1264],{"class":96},", size) ",[39,1266,1250],{"class":92},[39,1268,1269],{"class":96}," max_width:\n",[39,1271,1272,1275,1278],{"class":41,"line":193},[39,1273,1274],{"class":96},"        size ",[39,1276,1277],{"class":92},"-=",[39,1279,1280],{"class":156}," 0.5\n",[39,1282,1283,1285],{"class":41,"line":201},[39,1284,1006],{"class":92},[39,1286,1287],{"class":96}," size\n",[39,1289,1290],{"class":41,"line":210},[39,1291,136],{"emptyLinePlaceholder":135},[39,1293,1294,1296,1299,1302,1304,1306,1309,1311,1314],{"class":41,"line":218},[39,1295,863],{"class":92},[39,1297,1298],{"class":142}," draw_labels",[39,1300,1301],{"class":96},"(path, sheet, labels, skip",[39,1303,153],{"class":92},[39,1305,663],{"class":156},[39,1307,1308],{"class":96},", outline",[39,1310,153],{"class":92},[39,1312,1313],{"class":156},"False",[39,1315,1316],{"class":96},"):\n",[39,1318,1319,1322,1324,1327,1330,1332],{"class":41,"line":226},[39,1320,1321],{"class":96},"    c ",[39,1323,153],{"class":92},[39,1325,1326],{"class":96}," canvas.Canvas(path, ",[39,1328,1329],{"class":149},"pagesize",[39,1331,153],{"class":92},[39,1333,1334],{"class":96},"sheet.page)\n",[39,1336,1337,1340,1342,1345,1347],{"class":41,"line":234},[39,1338,1339],{"class":96},"    per_page ",[39,1341,153],{"class":92},[39,1343,1344],{"class":96}," sheet.cols ",[39,1346,320],{"class":92},[39,1348,1349],{"class":96}," sheet.rows\n",[39,1351,1352,1355,1358,1360,1363,1366,1369,1371],{"class":41,"line":242},[39,1353,1354],{"class":92},"    for",[39,1356,1357],{"class":96}," n, lines ",[39,1359,1023],{"class":92},[39,1361,1362],{"class":156}," enumerate",[39,1364,1365],{"class":96},"(labels, ",[39,1367,1368],{"class":149},"start",[39,1370,153],{"class":92},[39,1372,1373],{"class":96},"skip):\n",[39,1375,1376,1379,1382,1384,1386,1388,1391,1393,1396],{"class":41,"line":250},[39,1377,1378],{"class":92},"        if",[39,1380,1381],{"class":96}," n ",[39,1383,1035],{"class":92},[39,1385,1381],{"class":96},[39,1387,284],{"class":92},[39,1389,1390],{"class":96}," per_page ",[39,1392,917],{"class":92},[39,1394,1395],{"class":156}," 0",[39,1397,172],{"class":96},[39,1399,1400],{"class":41,"line":255},[39,1401,1402],{"class":96},"            c.showPage()\n",[39,1404,1405,1408,1410,1413,1415],{"class":41,"line":267},[39,1406,1407],{"class":96},"        x, y ",[39,1409,153],{"class":92},[39,1411,1412],{"class":96}," sheet.origin(n ",[39,1414,284],{"class":92},[39,1416,1417],{"class":96}," per_page)\n",[39,1419,1420,1422],{"class":41,"line":273},[39,1421,1378],{"class":92},[39,1423,1424],{"class":96}," outline:\n",[39,1426,1427,1430,1432,1434,1436],{"class":41,"line":301},[39,1428,1429],{"class":96},"            c.setDash(",[39,1431,737],{"class":156},[39,1433,407],{"class":96},[39,1435,737],{"class":156},[39,1437,160],{"class":96},[39,1439,1440],{"class":41,"line":328},[39,1441,1442],{"class":96},"            c.rect(x, y, sheet.width, sheet.height)\n",[39,1444,1445],{"class":41,"line":374},[39,1446,1447],{"class":96},"            c.setDash()\n",[39,1449,1450,1453,1455,1458,1460],{"class":41,"line":383},[39,1451,1452],{"class":96},"        line_h ",[39,1454,153],{"class":92},[39,1456,1457],{"class":156}," SIZE",[39,1459,428],{"class":92},[39,1461,1462],{"class":156}," 1.2\n",[39,1464,1465,1468,1470,1473,1475,1478,1480,1483,1486,1488,1491,1494,1497,1500,1502],{"class":41,"line":388},[39,1466,1467],{"class":96},"        text_y ",[39,1469,153],{"class":92},[39,1471,1472],{"class":96}," y ",[39,1474,314],{"class":92},[39,1476,1477],{"class":96}," (sheet.height ",[39,1479,314],{"class":92},[39,1481,1482],{"class":156}," len",[39,1484,1485],{"class":96},"(lines) ",[39,1487,320],{"class":92},[39,1489,1490],{"class":96}," line_h) ",[39,1492,1493],{"class":92},"\u002F",[39,1495,1496],{"class":156}," 2",[39,1498,1499],{"class":92}," -",[39,1501,1457],{"class":156},[39,1503,1505],{"class":1504},"s-wDw","    # centre the block vertically\n",[39,1507,1508,1511,1514,1516],{"class":41,"line":447},[39,1509,1510],{"class":92},"        for",[39,1512,1513],{"class":96}," line ",[39,1515,1023],{"class":92},[39,1517,1518],{"class":96}," lines:\n",[39,1520,1521,1524,1526,1529,1531,1533,1535,1538],{"class":41,"line":498},[39,1522,1523],{"class":96},"            c.setFont(",[39,1525,1178],{"class":156},[39,1527,1528],{"class":96},", fit_size(line, sheet.width ",[39,1530,347],{"class":92},[39,1532,1496],{"class":156},[39,1534,428],{"class":92},[39,1536,1537],{"class":156}," PAD",[39,1539,1540],{"class":96},"))\n",[39,1542,1543,1546,1548,1550],{"class":41,"line":550},[39,1544,1545],{"class":96},"            c.drawString(x ",[39,1547,314],{"class":92},[39,1549,1537],{"class":156},[39,1551,1552],{"class":96},", text_y, line)\n",[39,1554,1555,1558,1560],{"class":41,"line":598},[39,1556,1557],{"class":96},"            text_y ",[39,1559,1277],{"class":92},[39,1561,1562],{"class":96}," line_h\n",[39,1564,1566],{"class":41,"line":1565},29,[39,1567,1568],{"class":96},"    c.save()\n",[39,1570,1572],{"class":41,"line":1571},30,[39,1573,136],{"emptyLinePlaceholder":135},[39,1575,1577,1580,1583,1586,1589,1591,1593],{"class":41,"line":1576},31,[39,1578,1579],{"class":96},"draw_labels(",[39,1581,1582],{"class":49},"\"labels.pdf\"",[39,1584,1585],{"class":96},", L7160, labels, ",[39,1587,1588],{"class":149},"skip",[39,1590,153],{"class":92},[39,1592,737],{"class":156},[39,1594,160],{"class":96},[39,1596,1598,1600,1602,1605,1607,1609],{"class":41,"line":1597},32,[39,1599,601],{"class":156},[39,1601,146],{"class":96},[39,1603,1604],{"class":49},"\"labels.pdf written; first label drawn in position\"",[39,1606,407],{"class":96},[39,1608,737],{"class":156},[39,1610,160],{"class":96},[10,1612,1613,1616],{},[14,1614,1615],{},"skip=2"," starts in the third position, leaving the first two labels of a partly used sheet untouched — the next run can use them. A new page starts every 21 labels. The block of lines is centred vertically in the label, which looks better than top-aligned text when addresses have different numbers of lines. Dev Patel's long company name, about 60 mm wide at 10 points against 55.5 mm of usable label width, is drawn at 9 points so that it fits; with a 7-point minimum, a line that still does not fit is better shortened in the source data than printed illegibly small.",[641,1618,650,1624,650,1627,650,1630,650,1635,650,1638,650,1642,650,1646,650,1650,650,1653,650,1656,650,1660,650,1662,650,1665,650,1667,650,1670,650,1673,650,1676,650,1678,650,1681,650,1683,650,1686,650,1689,650,1692,650,1694,650,1697,650,1701,650,1704,650,1707,650,1709,650,1712,650,1714,650,1717,650,1720,650,1723,650,1725,650,1728,650,1730,650,1733,650,1737,650,1739,650,1742,650,1744,650,1747,650,1750,650,1754,650,1756,650,1758,650,1760,650,1762,650,1764,650,1767,650,1769,650,1772,650,1778,650,1781,650,1788,650,1793,650,1800],{"viewBox":1619,"role":644,"ariaLabelledBy":1620,"xmlns":648,"style":1623},"69 0 621 248",[1621,1622],"ml-clean-t","ml-clean-d","width:100%;max-width:621px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[652,1625,1626],{"id":1621},"A spreadsheet row becomes label lines",[656,1628,1629],{"id":1622},"The row for Ben Okafor has an empty company and an empty second address line. Only the lines with content remain, with the town in capitals and the postcode on its own line.",[660,1631],{"x":1632,"y":663,"width":1633,"height":1634,"fill":666},"69","621","248",[660,1636],{"x":1637,"y":705,"width":671,"height":672,"rx":663,"fill":673,"stroke":674,"style":675},"85.8",[660,1639],{"x":1640,"y":705,"width":1641,"height":672,"rx":663,"fill":673,"stroke":674,"style":675},"117.8","106.2",[681,1643,686],{"x":1644,"y":1645,"style":685},"170.9","57.0",[660,1647],{"x":1648,"y":705,"width":1649,"height":672,"rx":663,"fill":673,"stroke":674,"style":675},"224.0","124.4",[681,1651,694],{"x":1652,"y":1645,"style":685},"286.2",[660,1654],{"x":1637,"y":1655,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"64.0",[681,1657,341],{"x":1658,"y":1659,"style":685},"101.8","83.0",[660,1661],{"x":1640,"y":1655,"width":1641,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,1663,1664],{"x":1644,"y":1659,"style":716},"Column",[660,1666],{"x":1648,"y":1655,"width":1649,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,1668,1669],{"x":1652,"y":1659,"style":716},"Value",[660,1671],{"x":1637,"y":1672,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"92.0",[681,1674,737],{"x":1658,"y":1675,"style":685},"111.0",[660,1677],{"x":1640,"y":1672,"width":1641,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,1679,1680],{"x":1644,"y":1675,"style":785},"Name",[660,1682],{"x":1648,"y":1672,"width":1649,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,1684,1685],{"x":1652,"y":1675,"style":785},"Ben Okafor",[660,1687],{"x":1637,"y":1688,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"120.0",[681,1690,404],{"x":1658,"y":1691,"style":685},"139.0",[660,1693],{"x":1640,"y":1688,"width":1641,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,1695,1696],{"x":1644,"y":1691,"style":785},"Company",[660,1698],{"x":1648,"y":1688,"width":1649,"height":706,"rx":663,"fill":1699,"stroke":1700,"style":713},"#fce9e9","var(--danger,#dc2626)",[660,1702],{"x":1637,"y":1703,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"148.0",[681,1705,780],{"x":1658,"y":1706,"style":685},"167.0",[660,1708],{"x":1640,"y":1703,"width":1641,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,1710,1711],{"x":1644,"y":1706,"style":785},"Address 1",[660,1713],{"x":1648,"y":1703,"width":1649,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,1715,1716],{"x":1652,"y":1706,"style":785},"Flat 4, 9 Park Road",[660,1718],{"x":1637,"y":1719,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"176.0",[681,1721,802],{"x":1658,"y":1722,"style":685},"195.0",[660,1724],{"x":1640,"y":1719,"width":1641,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,1726,1727],{"x":1644,"y":1722,"style":785},"Address 2",[660,1729],{"x":1648,"y":1719,"width":1649,"height":706,"rx":663,"fill":1699,"stroke":1700,"style":713},[660,1731],{"x":1637,"y":1732,"width":671,"height":706,"rx":663,"fill":673,"stroke":674,"style":675},"204.0",[681,1734,1736],{"x":1658,"y":1735,"style":685},"223.0","6",[660,1738],{"x":1640,"y":1732,"width":1641,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,1740,1741],{"x":1644,"y":1735,"style":785},"City \u002F Postcode",[660,1743],{"x":1648,"y":1732,"width":1649,"height":706,"rx":663,"fill":666,"stroke":674,"style":675},[681,1745,1746],{"x":1652,"y":1735,"style":785},"Leeds · LS6 2QX",[660,1748],{"x":1749,"y":705,"width":1649,"height":706,"rx":663,"fill":673,"stroke":674,"style":713},"549.7",[681,1751,1753],{"x":1752,"y":710,"style":716},"612.0","Line",[660,1755],{"x":1749,"y":733,"width":1649,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},[681,1757,1685],{"x":1752,"y":736,"style":729},[660,1759],{"x":1749,"y":755,"width":1649,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},[681,1761,1716],{"x":1752,"y":758,"style":729},[660,1763],{"x":1749,"y":776,"width":1649,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},[681,1765,1766],{"x":1752,"y":779,"style":729},"LEEDS",[660,1768],{"x":1749,"y":798,"width":1649,"height":706,"rx":663,"fill":725,"stroke":726,"style":713},[681,1770,1771],{"x":1752,"y":801,"style":729},"LS6 2QX",[681,1773,1777],{"x":1774,"y":1775,"style":1776},"217.1","29.0","font-size:12.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","Excel row",[681,1779,1780],{"x":1752,"y":1775,"style":1776},"label",[41,1782],{"x1":1783,"y1":1784,"x2":1785,"y2":1784,"stroke":1786,"style":1787},"358.4","110.0","535.7","var(--brand,#5b5cf0)","stroke-width:2px",[1789,1790],"polygon",{"points":1791,"fill":1792},"539.7,110.0 530.7,115.0 530.7,105.0","#5b5cf0",[660,1794],{"x":1795,"y":1796,"width":1797,"height":1798,"rx":795,"fill":666,"stroke":674,"style":1799},"384.6","77.0","129.0","22.0","stroke-width:1.2px",[681,1801,1804],{"x":1802,"y":1672,"style":1803},"449.1","font-size:11.5px;font-weight:400;fill:var(--brand-strong,#4338ca);text-anchor:middle;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace","address_lines()",[25,1806,1808],{"id":1807},"step-4-print-an-alignment-test-first","Step 4 — Print an alignment test first",[10,1810,1811,1812,1815,1816,1818],{},"Printers shift and scale. Before using a sheet of labels, print the dashed outlines on plain paper, hold it against a label sheet up to the light, and adjust ",[14,1813,1814],{},"left"," and ",[14,1817,462],{}," if the boxes do not line up:",[30,1820,1822],{"className":83,"code":1821,"language":85,"meta":35,"style":35},"draw_labels(\"alignment_test.pdf\", L7160, [[\"Alignment test\"]] * 21, outline=True)\nprint(\"21 outlined test labels\")\n",[14,1823,1824,1856],{"__ignoreMap":35},[39,1825,1826,1828,1831,1834,1837,1840,1842,1845,1847,1850,1852,1854],{"class":41,"line":42},[39,1827,1579],{"class":96},[39,1829,1830],{"class":49},"\"alignment_test.pdf\"",[39,1832,1833],{"class":96},", L7160, [[",[39,1835,1836],{"class":49},"\"Alignment test\"",[39,1838,1839],{"class":96},"]] ",[39,1841,320],{"class":92},[39,1843,1844],{"class":156}," 21",[39,1846,407],{"class":96},[39,1848,1849],{"class":149},"outline",[39,1851,153],{"class":92},[39,1853,157],{"class":156},[39,1855,160],{"class":96},[39,1857,1858,1860,1862,1865],{"class":41,"line":106},[39,1859,601],{"class":156},[39,1861,146],{"class":96},[39,1863,1864],{"class":49},"\"21 outlined test labels\"",[39,1866,160],{"class":96},[10,1868,1869,1870,1874,1875,1878],{},"Print at ",[1871,1872,1873],"strong",{},"actual size"," — \"Fit to page\" or \"Shrink oversized pages\" in the print dialog scales the whole page by a few percent and moves every label off its mark, more so towards the bottom of the sheet. Once the outlines match, keep the corrected measurements in the ",[14,1876,1877],{},"LabelSheet"," definition for that printer.",[641,1880,650,1886,650,1889,650,1892,650,1896,650,1902,650,1913,650,1919,650,1924,650,1928,650,1933,650,1936,650,1940,650,1947,650,1953,650,1957,650,1961,650,1964,650,1969,650,1976,650,1981,650,1984,650,1988,650,1991,650,1994,650,2001,650,2006],{"viewBox":1881,"role":644,"ariaLabelledBy":1882,"xmlns":648,"style":1885},"4 0 752 142",[1883,1884],"ml-align-t","ml-align-d","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[652,1887,1888],{"id":1883},"Calibrating a printer for a label sheet",[656,1890,1891],{"id":1884},"Print the outlined test page on plain paper at actual size, hold it against a label sheet against the light, adjust the left and top margins if the outlines are off, and print the real labels once they match.",[660,1893],{"x":780,"y":663,"width":1894,"height":1895,"fill":666},"752","142",[660,1897],{"x":1898,"y":670,"width":1899,"height":1900,"rx":1901,"fill":673,"stroke":674,"style":1787},"20.0","153.0","110.5","12",[1903,1904,1906],"g",{"transform":1905},"translate(84.5,29.0) scale(1.000)",[1907,1908],"path",{"d":1909,"fill":1910,"stroke":1911,"style":1912},"M6 3h9l4 4v14H6z M15 3v4h4","none","var(--text,#172033)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[681,1914,1918],{"x":1915,"y":1916,"style":1917},"96.5","75.5","font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Print outlines",[681,1920,1923],{"x":1915,"y":1921,"style":1922},"95.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","plain paper, actual",[681,1925,1927],{"x":1915,"y":1926,"style":1922},"112.5","size",[41,1929],{"x1":1930,"y1":1931,"x2":1932,"y2":1931,"stroke":1786,"style":1787},"178.0","71.2","200.0",[1789,1934],{"points":1935,"fill":1792},"204.0,71.2 195.0,76.2 195.0,66.2",[660,1937],{"x":1938,"y":670,"width":1899,"height":1900,"rx":1901,"fill":1939,"stroke":1786,"style":1787},"209.0","#f0f4ff",[1903,1941,1943],{"transform":1942},"translate(273.5,37.8) scale(1.000)",[1907,1944],{"d":1945,"fill":1910,"stroke":1946,"style":1912},"M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12z M12 9a3 3 0 1 0 .01 0z","var(--brand-strong,#4338ca)",[681,1948,1952],{"x":1949,"y":1950,"style":1951},"285.5","84.2","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Compare",[681,1954,1956],{"x":1949,"y":1955,"style":1922},"103.8","against a label sheet",[41,1958],{"x1":1959,"y1":1931,"x2":1960,"y2":1931,"stroke":1786,"style":1787},"367.0","389.0",[1789,1962],{"points":1963,"fill":1792},"393.0,71.2 384.0,76.2 384.0,66.2",[660,1965],{"x":1966,"y":670,"width":1899,"height":1900,"rx":1901,"fill":1967,"stroke":1968,"style":1787},"398.0","#fdefd8","var(--gold,#b4740a)",[1903,1970,1972],{"transform":1971},"translate(462.5,37.8) scale(1.000)",[1907,1973],{"d":1974,"fill":1910,"stroke":1975,"style":1912},"M12 9a3 3 0 1 0 .01 0z M12 2.5v3 M12 18.5v3 M2.5 12h3 M18.5 12h3 M5.3 5.3l2.1 2.1 M16.6 16.6l2.1 2.1 M5.3 18.7l2.1-2.1 M16.6 7.4l2.1-2.1","var(--gold-ink,#7a4e06)",[681,1977,1980],{"x":1978,"y":1950,"style":1979},"474.5","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Adjust",[681,1982,1983],{"x":1978,"y":1955,"style":1922},"left and top margins",[41,1985],{"x1":1986,"y1":1931,"x2":1987,"y2":1931,"stroke":1786,"style":1787},"556.0","578.0",[1789,1989],{"points":1990,"fill":1792},"582.0,71.2 573.0,76.2 573.0,66.2",[660,1992],{"x":1993,"y":670,"width":1899,"height":1900,"rx":1901,"fill":725,"stroke":726,"style":1787},"587.0",[1903,1995,1997],{"transform":1996},"translate(651.5,37.8) scale(1.000)",[1907,1998],{"d":1999,"fill":1910,"stroke":2000,"style":1912},"M5 12.5l4.5 4.5L19 7","var(--teal-ink,#0b6157)",[681,2002,2005],{"x":2003,"y":1950,"style":2004},"663.5","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Print labels",[681,2007,2008],{"x":2003,"y":1955,"style":1922},"measurements saved",[25,2010,2012],{"id":2011},"step-5-check-every-address-landed-inside-its-label","Step 5 — Check every address landed inside its label",[10,2014,2015],{},"Text placement is easy to get subtly wrong, so verify it from the PDF: read where each line was drawn and confirm it falls inside a label rectangle:",[30,2017,2019],{"className":83,"code":2018,"language":85,"meta":35,"style":35},"from pypdf import PdfReader\n\nplaced = []\ndef visitor(text, cm, tm, font_dict, font_size):\n    if text.strip():\n        placed.append((text.strip(), tm[4], tm[5]))\n\nPdfReader(\"labels.pdf\").pages[0].extract_text(visitor_text=visitor)\n\ndef inside_a_label(x, y, sheet):\n    return any(ox + 2 \u003C= x \u003C= ox + sheet.width - 2 and oy \u003C= y \u003C= oy + sheet.height\n               for ox, oy in (sheet.origin(i) for i in range(sheet.cols * sheet.rows)))\n\noutside = [t for t, x, y in placed if not inside_a_label(x, y, L7160)]\nwidest = max(stringWidth(t, FONT, MIN_SIZE) for t, _, _ in placed)\nprint(len(placed), \"lines drawn; outside a label:\", outside)\nprint(\"every line fits the label width:\", all(stringWidth(t, FONT, fit_size(t, L7160.width - 2 * PAD)) \u003C= L7160.width - 2 * PAD\n                                               for t, _, _ in placed), \"| widest at minimum size:\", round(widest \u002F mm, 1), \"mm\")\n",[14,2020,2021,2033,2037,2047,2057,2064,2079,2083,2106,2110,2120,2173,2204,2208,2236,2268,2286,2332],{"__ignoreMap":35},[39,2022,2023,2025,2028,2030],{"class":41,"line":42},[39,2024,93],{"class":92},[39,2026,2027],{"class":96}," pypdf ",[39,2029,100],{"class":92},[39,2031,2032],{"class":96}," PdfReader\n",[39,2034,2035],{"class":41,"line":106},[39,2036,136],{"emptyLinePlaceholder":135},[39,2038,2039,2042,2044],{"class":41,"line":119},[39,2040,2041],{"class":96},"placed ",[39,2043,153],{"class":92},[39,2045,2046],{"class":96}," []\n",[39,2048,2049,2051,2054],{"class":41,"line":132},[39,2050,863],{"class":92},[39,2052,2053],{"class":142}," visitor",[39,2055,2056],{"class":96},"(text, cm, tm, font_dict, font_size):\n",[39,2058,2059,2061],{"class":41,"line":139},[39,2060,906],{"class":92},[39,2062,2063],{"class":96}," text.strip():\n",[39,2065,2066,2069,2071,2074,2076],{"class":41,"line":163},[39,2067,2068],{"class":96},"        placed.append((text.strip(), tm[",[39,2070,780],{"class":156},[39,2072,2073],{"class":96},"], tm[",[39,2075,802],{"class":156},[39,2077,2078],{"class":96},"]))\n",[39,2080,2081],{"class":41,"line":175},[39,2082,136],{"emptyLinePlaceholder":135},[39,2084,2085,2088,2090,2093,2095,2098,2101,2103],{"class":41,"line":184},[39,2086,2087],{"class":96},"PdfReader(",[39,2089,1582],{"class":49},[39,2091,2092],{"class":96},").pages[",[39,2094,663],{"class":156},[39,2096,2097],{"class":96},"].extract_text(",[39,2099,2100],{"class":149},"visitor_text",[39,2102,153],{"class":92},[39,2104,2105],{"class":96},"visitor)\n",[39,2107,2108],{"class":41,"line":193},[39,2109,136],{"emptyLinePlaceholder":135},[39,2111,2112,2114,2117],{"class":41,"line":201},[39,2113,863],{"class":92},[39,2115,2116],{"class":142}," inside_a_label",[39,2118,2119],{"class":96},"(x, y, sheet):\n",[39,2121,2122,2124,2127,2130,2132,2134,2137,2140,2143,2146,2148,2151,2153,2155,2157,2160,2162,2164,2166,2168,2170],{"class":41,"line":210},[39,2123,1006],{"class":92},[39,2125,2126],{"class":156}," any",[39,2128,2129],{"class":96},"(ox ",[39,2131,314],{"class":92},[39,2133,1496],{"class":156},[39,2135,2136],{"class":92}," \u003C=",[39,2138,2139],{"class":96}," x ",[39,2141,2142],{"class":92},"\u003C=",[39,2144,2145],{"class":96}," ox ",[39,2147,314],{"class":92},[39,2149,2150],{"class":96}," sheet.width ",[39,2152,347],{"class":92},[39,2154,1496],{"class":156},[39,2156,1256],{"class":92},[39,2158,2159],{"class":96}," oy ",[39,2161,2142],{"class":92},[39,2163,1472],{"class":96},[39,2165,2142],{"class":92},[39,2167,2159],{"class":96},[39,2169,314],{"class":92},[39,2171,2172],{"class":96}," sheet.height\n",[39,2174,2175,2178,2181,2183,2186,2188,2191,2193,2196,2199,2201],{"class":41,"line":218},[39,2176,2177],{"class":92},"               for",[39,2179,2180],{"class":96}," ox, oy ",[39,2182,1023],{"class":92},[39,2184,2185],{"class":96}," (sheet.origin(i) ",[39,2187,1017],{"class":92},[39,2189,2190],{"class":96}," i ",[39,2192,1023],{"class":92},[39,2194,2195],{"class":156}," range",[39,2197,2198],{"class":96},"(sheet.cols ",[39,2200,320],{"class":92},[39,2202,2203],{"class":96}," sheet.rows)))\n",[39,2205,2206],{"class":41,"line":226},[39,2207,136],{"emptyLinePlaceholder":135},[39,2209,2210,2213,2215,2218,2220,2223,2225,2228,2230,2233],{"class":41,"line":234},[39,2211,2212],{"class":96},"outside ",[39,2214,153],{"class":92},[39,2216,2217],{"class":96}," [t ",[39,2219,1017],{"class":92},[39,2221,2222],{"class":96}," t, x, y ",[39,2224,1023],{"class":92},[39,2226,2227],{"class":96}," placed ",[39,2229,1029],{"class":92},[39,2231,2232],{"class":92}," not",[39,2234,2235],{"class":96}," inside_a_label(x, y, L7160)]\n",[39,2237,2238,2241,2243,2246,2249,2251,2253,2255,2258,2260,2263,2265],{"class":41,"line":242},[39,2239,2240],{"class":96},"widest ",[39,2242,153],{"class":92},[39,2244,2245],{"class":156}," max",[39,2247,2248],{"class":96},"(stringWidth(t, ",[39,2250,1178],{"class":156},[39,2252,407],{"class":96},[39,2254,1188],{"class":156},[39,2256,2257],{"class":96},") ",[39,2259,1017],{"class":92},[39,2261,2262],{"class":96}," t, _, _ ",[39,2264,1023],{"class":92},[39,2266,2267],{"class":96}," placed)\n",[39,2269,2270,2272,2274,2277,2280,2283],{"class":41,"line":250},[39,2271,601],{"class":156},[39,2273,146],{"class":96},[39,2275,2276],{"class":156},"len",[39,2278,2279],{"class":96},"(placed), ",[39,2281,2282],{"class":49},"\"lines drawn; outside a label:\"",[39,2284,2285],{"class":96},", outside)\n",[39,2287,2288,2290,2292,2295,2297,2300,2302,2304,2307,2309,2311,2313,2315,2318,2320,2323,2325,2327,2329],{"class":41,"line":255},[39,2289,601],{"class":156},[39,2291,146],{"class":96},[39,2293,2294],{"class":49},"\"every line fits the label width:\"",[39,2296,407],{"class":96},[39,2298,2299],{"class":156},"all",[39,2301,2248],{"class":96},[39,2303,1178],{"class":156},[39,2305,2306],{"class":96},", fit_size(t, L7160.width ",[39,2308,347],{"class":92},[39,2310,1496],{"class":156},[39,2312,428],{"class":92},[39,2314,1537],{"class":156},[39,2316,2317],{"class":96},")) ",[39,2319,2142],{"class":92},[39,2321,2322],{"class":96}," L7160.width ",[39,2324,347],{"class":92},[39,2326,1496],{"class":156},[39,2328,428],{"class":92},[39,2330,2331],{"class":156}," PAD\n",[39,2333,2334,2337,2339,2341,2344,2347,2349,2352,2355,2357,2359,2361,2364,2367],{"class":41,"line":267},[39,2335,2336],{"class":92},"                                               for",[39,2338,2262],{"class":96},[39,2340,1023],{"class":92},[39,2342,2343],{"class":96}," placed), ",[39,2345,2346],{"class":49},"\"| widest at minimum size:\"",[39,2348,407],{"class":96},[39,2350,2351],{"class":156},"round",[39,2353,2354],{"class":96},"(widest ",[39,2356,1493],{"class":92},[39,2358,431],{"class":96},[39,2360,341],{"class":156},[39,2362,2363],{"class":96},"), ",[39,2365,2366],{"class":49},"\"mm\"",[39,2368,160],{"class":96},[10,2370,2371,2372,2374],{},"pypdf's ",[14,2373,2100],{}," callback reports each text run with its transformation matrix, whose last two values are the x and y position on the page. Every line started inside a label, and every line fits within the label's inner width at the size it was drawn. A check like this belongs in a test of the label job, so a change to the address rules or the sheet definition cannot quietly push text across a label edge.",[25,2376,2378],{"id":2377},"variations","Variations",[2380,2381,2382,2389,2395,2405],"ul",{},[2383,2384,2385,2388],"li",{},[1871,2386,2387],{},"Return labels or a sender line."," Add a small first line in 6-point text with your return address above the recipient.",[2383,2390,2391,2394],{},[1871,2392,2393],{},"Labels sorted for posting."," Sort the DataFrame by country and postcode before drawing so sacks of mail can be bundled.",[2383,2396,2397,2400,2401,2404],{},[1871,2398,2399],{},"Barcodes or QR codes."," reportlab's barcode module (",[14,2402,2403],{},"graphics.barcode",") draws them inside the label next to the text.",[2383,2406,2407,2410,2411,23],{},[1871,2408,2409],{},"One letter per contact instead of labels."," Use the same address lines in a document template; see ",[19,2412,2414],{"href":2413},"\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fgenerate-word-documents-from-excel-rows\u002F","Generate Word Documents from Excel Rows",[25,2416,2418],{"id":2417},"common-pitfalls","Common pitfalls",[2380,2420,2421,2429,2435,2441,2447],{},[2383,2422,2423,2426,2427,23],{},[1871,2424,2425],{},"Postcodes read as numbers."," Read the file with ",[14,2428,1124],{},[2383,2430,2431,2434],{},[1871,2432,2433],{},"Gaps for empty columns."," Drop blank and whitespace-only lines.",[2383,2436,2437,2440],{},[1871,2438,2439],{},"Printing with \"Fit to page\"."," Print at actual size or every label drifts.",[2383,2442,2443,2446],{},[1871,2444,2445],{},"Measuring from the top in reportlab."," Its origin is the bottom-left; convert.",[2383,2448,2449,2452],{},[1871,2450,2451],{},"Wasting part-used sheets."," Use a starting offset.",[25,2454,2456],{"id":2455},"conclusion","Conclusion",[10,2458,2459],{},"Printing mailing labels from Excel needs three pieces: a label-sheet definition taken from the product's measurements, a function that turns each row into clean address lines, and a reportlab loop that draws each label at its origin, shrinking long lines and starting part-way down a used sheet. Print an outlined alignment page at actual size before using real labels, and check from the PDF that every line landed inside its label.",[25,2461,2463],{"id":2462},"frequently-asked-questions","Frequently asked questions",[10,2465,2466,2469],{},[1871,2467,2468],{},"How do I print address labels from an Excel list with Python?","\nRead the list with pandas, build the address lines for each row, and draw them with reportlab at positions computed from the label sheet's margins, label size and pitch. Print the resulting PDF at actual size.",[10,2471,2472,2475],{},[1871,2473,2474],{},"What measurements do I need for a label sheet?","\nPage size, label width and height, the number of columns and rows, the top and left margins, and the horizontal and vertical pitch. They are printed on the box or in the manufacturer's template.",[10,2477,2478,2481],{},[1871,2479,2480],{},"How do I skip labels already used on a sheet?","\nStart numbering at an offset, for example skip=2 to leave the first two positions empty, so printing begins on the first unused label.",[10,2483,2484,2487],{},[1871,2485,2486],{},"Why are my labels slightly out of line?","\nUsually the print dialog is scaling the page. Print at actual size, test with outlined labels on plain paper, and adjust the margins in the sheet definition if needed.",[25,2489,2491],{"id":2490},"related","Related",[2380,2493,2494,2500,2507,2514],{},[2383,2495,2496,2497,2499],{},"Up one level: ",[19,2498,22],{"href":21}," — documents built from spreadsheet data.",[2383,2501,2502,2506],{},[19,2503,2505],{"href":2504},"\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fgenerate-customer-account-statements-from-a-ledger\u002F","Generate Customer Account Statements from a Ledger"," — a document per customer from the same kind of list.",[2383,2508,2509,2513],{},[19,2510,2512],{"href":2511},"\u002Fautomating-reporting-workflows\u002Fexporting-excel-reports-to-pdf\u002Fadd-bookmarks-and-a-cover-page-to-an-excel-pdf-export\u002F","Add Bookmarks and a Cover Page to an Excel PDF Export"," — another reportlab-drawn page.",[2383,2515,2516,2520],{},[19,2517,2519],{"href":2518},"\u002Fautomating-reporting-workflows\u002Femailing-excel-reports-with-smtplib\u002Fsend-each-recipient-their-own-excel-report\u002F","Send Each Recipient Their Own Excel Report"," — the email version of a mail merge.",[2522,2523,2524],"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 .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}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 .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}",{"title":35,"searchDepth":106,"depth":106,"links":2526},[2527,2528,2529,2530,2531,2532,2533,2534,2535,2536,2537],{"id":27,"depth":106,"text":28},{"id":71,"depth":106,"text":72},{"id":818,"depth":106,"text":819},{"id":1136,"depth":106,"text":1137},{"id":1807,"depth":106,"text":1808},{"id":2011,"depth":106,"text":2012},{"id":2377,"depth":106,"text":2378},{"id":2417,"depth":106,"text":2418},{"id":2455,"depth":106,"text":2456},{"id":2462,"depth":106,"text":2463},{"id":2490,"depth":106,"text":2491},"2026-10-02","Turn an Excel address list into a print-ready PDF of mailing labels with pandas and reportlab: describe a label sheet such as Avery L7160 or 5160 by its measurements, tidy addresses by dropping blank lines, shrink long lines to fit, start on a partly used sheet, print an alignment test, and check every address landed inside its label.","md",[2542,2544,2546,2548],{"q":2468,"a":2543},"Read the list with pandas, build the address lines for each row, and draw them with reportlab at positions computed from the label sheet's margins, label size and pitch. Print the resulting PDF at actual size.",{"q":2474,"a":2545},"Page size, label width and height, the number of columns and rows, the top and left margins, and the horizontal and vertical pitch. They are printed on the box or in the manufacturer's template.",{"q":2480,"a":2547},"Start numbering at an offset, for example skip=2 to leave the first two positions empty, so printing begins on the first unused label.",{"q":2486,"a":2549},"Usually the print dialog is scaling the page. Print at actual size, test with outlined labels on plain paper, and adjust the margins in the sheet definition if needed.","print mailing labels from an excel address list",null,{"breadcrumb":2553},[2554,2556,2559],{"name":2555,"item":1493},"Home",{"name":2557,"item":2558},"Automating Reporting Workflows with Python and Excel","\u002Fautomating-reporting-workflows\u002F",{"name":22,"item":21},"\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fprint-mailing-labels-from-an-excel-address-list",{"title":2562,"description":2563},"Print Mailing Labels from an Excel Address List with Python","Generate label sheets from Excel addresses with pandas and reportlab: Avery L7160 and 5160 layouts from measurements, blank-line cleanup, shrink-to-fit text, starting position, alignment sheet and a placement test.","print-mailing-labels-from-an-excel-address-list","automating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fprint-mailing-labels-from-an-excel-address-list\u002Findex",[2567,2568],"report-layouts","pdf-export","how-to","_8S_viQd_7bajbLWoKaAw1T8HqZIfoZt2ft0GJ7WPj0",[2572,2576],{"title":2573,"path":2574,"stem":2575,"children":-1},"Populate an Excel Template Without Losing Formatting","\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fpopulate-excel-template-without-losing-formatting","automating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fpopulate-excel-template-without-losing-formatting\u002Findex",{"title":2577,"path":2578,"stem":2579,"children":-1},"Repeat a Template Block for Each Record in an Excel Report","\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Frepeat-a-template-block-for-each-record","automating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Frepeat-a-template-block-for-each-record\u002Findex",[2581,2583],{"path":2582,"title":22},"\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates",{"path":2584,"title":2557},"\u002Fautomating-reporting-workflows",[],[2587,2591,2594,2597,2600,2603],{"path":2588,"title":2589,"kind":2590},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports","Building Finance and Operations Reports in Excel with Python","guide",{"path":2592,"title":2593,"kind":2569},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fallocate-shared-costs-across-departments","Allocate Shared Costs Across Departments with Python",{"path":2595,"title":2596,"kind":2569},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-bank-reconciliation-report","Build a Bank Reconciliation Report with Python and Excel",{"path":2598,"title":2599,"kind":2569},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-bill-of-materials-cost-rollup","Build a Bill of Materials Cost Rollup",{"path":2601,"title":2602,"kind":2569},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-break-even-analysis-in-excel-with-python","Build a Break-Even Analysis in Excel with Python",{"path":2604,"title":2605,"kind":2606},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-budget-vs-actual-variance-report","Build a Budget vs Actual Variance Report in Excel with Python","compare",1790972138236]