[{"data":1,"prerenderedAt":2390},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Ftranspose-a-range-of-cells-with-openpyxl":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Ftranspose-a-range-of-cells-with-openpyxl":2355,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Ftranspose-a-range-of-cells-with-openpyxl":2364,"children:\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Ftranspose-a-range-of-cells-with-openpyxl":2369,"related:\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Ftranspose-a-range-of-cells-with-openpyxl":2370},{"id":4,"title":5,"body":6,"dateModified":2322,"datePublished":2322,"description":2323,"extension":2324,"faq":2325,"keyword":2334,"kind":2335,"meta":2336,"navigation":397,"path":2344,"seo":2345,"slug":2348,"stem":2349,"topics":2350,"type":2353,"__hash__":2354},"docs\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Ftranspose-a-range-of-cells-with-openpyxl\u002Findex.md","Transpose a Range of Cells with openpyxl",{"type":7,"value":8,"toc":2309},"minimark",[9,19,24,53,63,351,355,369,587,597,601,616,927,960,1245,1249,1252,1390,1398,1402,1405,1625,1640,1644,1651,1742,1770,1774,1781,1862,1865,1919,2011,2021,2158,2162,2216,2220,2241,2245,2251,2257,2266,2272,2276,2305],[10,11,12,13,18],"p",{},"Data often arrives the wrong way round for the next step: months across the top when a chart or a pivot wants them down the side, one column per store when a database load wants one row per store, a questionnaire with questions across and respondents down. Excel's Paste Special → Transpose fixes it by hand. openpyxl has no transpose method, but because a range is just rows of cells, swapping the row and column index is a few lines — the extra work is in keeping the formatting and deciding whether the result should be a copy or stay linked to the source. This page is part of ",[14,15,17],"a",{"href":16},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002F","Using openpyxl for Excel File Manipulation",".",[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 openpyxl pandas\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}," openpyxl",[35,51,52],{"class":45}," pandas\n",[10,54,55,58,59,62],{},[32,56,57],{},"monthly.xlsx"," has a small, formatted table on the ",[32,60,61],{},"Monthly"," sheet: months across the top in white on indigo, three metrics down the side on a pale fill, and a different number format on each row — currency-style for revenue, whole numbers for orders, percentages for margin. After transposing, those formats have to follow the values into columns.",[64,65,73,74,73,78,73,82,73,90,73,99,73,103,73,110,73,114,73,118,73,122,73,126,73,130,73,134,73,138,73,143,73,148,73,152,73,154,73,157,73,159,73,162,73,164,73,167,73,170,73,174,73,178,73,182,73,184,73,188,73,190,73,193,73,195,73,198,73,201,73,205,73,207,73,210,73,212,73,215,73,217,73,220,73,222,73,225,73,228,73,232,73,235,73,239,73,242,73,246,73,249,73,251,73,254,73,256,73,258,73,260,73,262,73,264,73,266,73,268,73,270,73,272,73,274,73,276,73,278,73,280,73,282,73,284,73,286,73,288,73,290,73,292,73,294,73,296,73,298,73,301,73,304,73,306,73,308,73,310,73,312,73,314,73,316,73,322,73,326,73,332,73,337,73,345],"svg",{"viewBox":66,"role":67,"ariaLabelledBy":68,"xmlns":71,"style":72},"4 0 752 192","img",[69,70],"tr-swap-t","tr-swap-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  ",[75,76,77],"title",{"id":69},"Rows become columns and columns become rows",[79,80,81],"desc",{"id":70},"On the left a table with metrics down the side and months across the top. On the right the same table transposed, with months down the side and metrics across the top.",[83,84],"rect",{"x":85,"y":86,"width":87,"height":88,"fill":89},"4","0","752","192","#ffffff",[83,91],{"x":92,"y":93,"width":94,"height":95,"rx":86,"fill":96,"stroke":97,"style":98},"20.0","40.0","32.0","24.0","#e7ebef","var(--line,#cdd5e6)","stroke-width:1px",[83,100],{"x":101,"y":93,"width":102,"height":95,"rx":86,"fill":96,"stroke":97,"style":98},"52.0","61.3",[104,105,109],"text",{"x":106,"y":107,"style":108},"82.7","57.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[83,111],{"x":112,"y":93,"width":113,"height":95,"rx":86,"fill":96,"stroke":97,"style":98},"113.3","50.4",[104,115,117],{"x":116,"y":107,"style":108},"138.5","B",[83,119],{"x":120,"y":93,"width":121,"height":95,"rx":86,"fill":96,"stroke":97,"style":98},"163.7","54.8",[104,123,125],{"x":124,"y":107,"style":108},"191.1","C",[83,127],{"x":128,"y":93,"width":129,"height":95,"rx":86,"fill":96,"stroke":97,"style":98},"218.5","52.4",[104,131,133],{"x":132,"y":107,"style":108},"244.7","D",[83,135],{"x":92,"y":136,"width":94,"height":137,"rx":86,"fill":96,"stroke":97,"style":98},"64.0","28.0",[104,139,142],{"x":140,"y":141,"style":108},"36.0","83.0","1",[83,144],{"x":101,"y":136,"width":102,"height":137,"rx":86,"fill":145,"stroke":146,"style":147},"#f0f4ff","var(--brand,#5b5cf0)","stroke-width:1.5px",[104,149,151],{"x":106,"y":141,"style":150},"font-size:11px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Metric",[83,153],{"x":112,"y":136,"width":113,"height":137,"rx":86,"fill":145,"stroke":146,"style":147},[104,155,156],{"x":116,"y":141,"style":150},"Jan",[83,158],{"x":120,"y":136,"width":121,"height":137,"rx":86,"fill":145,"stroke":146,"style":147},[104,160,161],{"x":124,"y":141,"style":150},"Feb",[83,163],{"x":128,"y":136,"width":129,"height":137,"rx":86,"fill":145,"stroke":146,"style":147},[104,165,166],{"x":132,"y":141,"style":150},"Mar",[83,168],{"x":92,"y":169,"width":94,"height":137,"rx":86,"fill":96,"stroke":97,"style":98},"92.0",[104,171,173],{"x":140,"y":172,"style":108},"111.0","2",[83,175],{"x":101,"y":169,"width":102,"height":137,"rx":86,"fill":176,"stroke":177,"style":147},"#d9f4f1","var(--teal,#0f9488)",[104,179,181],{"x":106,"y":172,"style":180},"font-size:11px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Revenue",[83,183],{"x":112,"y":169,"width":113,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,185,187],{"x":116,"y":172,"style":186},"font-size:11px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","48,211",[83,189],{"x":120,"y":169,"width":121,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,191,192],{"x":124,"y":172,"style":186},"45,020",[83,194],{"x":128,"y":169,"width":129,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,196,197],{"x":132,"y":172,"style":186},"51,980",[83,199],{"x":92,"y":200,"width":94,"height":137,"rx":86,"fill":96,"stroke":97,"style":98},"120.0",[104,202,204],{"x":140,"y":203,"style":108},"139.0","3",[83,206],{"x":101,"y":200,"width":102,"height":137,"rx":86,"fill":176,"stroke":177,"style":147},[104,208,209],{"x":106,"y":203,"style":180},"Orders",[83,211],{"x":112,"y":200,"width":113,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,213,214],{"x":116,"y":203,"style":186},"1,284",[83,216],{"x":120,"y":200,"width":121,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,218,219],{"x":124,"y":203,"style":186},"1,190",[83,221],{"x":128,"y":200,"width":129,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,223,224],{"x":132,"y":203,"style":186},"1,377",[83,226],{"x":227,"y":93,"width":94,"height":95,"rx":86,"fill":96,"stroke":97,"style":98},"544.9",[83,229],{"x":230,"y":93,"width":231,"height":95,"rx":86,"fill":96,"stroke":97,"style":98},"576.9","50.1",[104,233,109],{"x":234,"y":107,"style":108},"601.9",[83,236],{"x":237,"y":93,"width":238,"height":95,"rx":86,"fill":96,"stroke":97,"style":98},"627.0","60.9",[104,240,117],{"x":241,"y":107,"style":108},"657.4",[83,243],{"x":244,"y":93,"width":245,"height":95,"rx":86,"fill":96,"stroke":97,"style":98},"687.9","52.1",[104,247,125],{"x":248,"y":107,"style":108},"713.9",[83,250],{"x":227,"y":136,"width":94,"height":137,"rx":86,"fill":96,"stroke":97,"style":98},[104,252,142],{"x":253,"y":141,"style":108},"560.9",[83,255],{"x":230,"y":136,"width":231,"height":137,"rx":86,"fill":145,"stroke":146,"style":147},[104,257,151],{"x":234,"y":141,"style":150},[83,259],{"x":237,"y":136,"width":238,"height":137,"rx":86,"fill":145,"stroke":146,"style":147},[104,261,181],{"x":241,"y":141,"style":150},[83,263],{"x":244,"y":136,"width":245,"height":137,"rx":86,"fill":145,"stroke":146,"style":147},[104,265,209],{"x":248,"y":141,"style":150},[83,267],{"x":227,"y":169,"width":94,"height":137,"rx":86,"fill":96,"stroke":97,"style":98},[104,269,173],{"x":253,"y":172,"style":108},[83,271],{"x":230,"y":169,"width":231,"height":137,"rx":86,"fill":176,"stroke":177,"style":147},[104,273,156],{"x":234,"y":172,"style":180},[83,275],{"x":237,"y":169,"width":238,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,277,187],{"x":241,"y":172,"style":186},[83,279],{"x":244,"y":169,"width":245,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,281,214],{"x":248,"y":172,"style":186},[83,283],{"x":227,"y":200,"width":94,"height":137,"rx":86,"fill":96,"stroke":97,"style":98},[104,285,204],{"x":253,"y":203,"style":108},[83,287],{"x":230,"y":200,"width":231,"height":137,"rx":86,"fill":176,"stroke":177,"style":147},[104,289,161],{"x":234,"y":203,"style":180},[83,291],{"x":237,"y":200,"width":238,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,293,192],{"x":241,"y":203,"style":186},[83,295],{"x":244,"y":200,"width":245,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,297,219],{"x":248,"y":203,"style":186},[83,299],{"x":227,"y":300,"width":94,"height":137,"rx":86,"fill":96,"stroke":97,"style":98},"148.0",[104,302,85],{"x":253,"y":303,"style":108},"167.0",[83,305],{"x":230,"y":300,"width":231,"height":137,"rx":86,"fill":176,"stroke":177,"style":147},[104,307,166],{"x":234,"y":303,"style":180},[83,309],{"x":237,"y":300,"width":238,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,311,197],{"x":241,"y":303,"style":186},[83,313],{"x":244,"y":300,"width":245,"height":137,"rx":86,"fill":89,"stroke":97,"style":98},[104,315,224],{"x":248,"y":303,"style":186},[104,317,321],{"x":318,"y":319,"style":320},"145.5","29.0","font-size:12.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","before",[104,323,325],{"x":324,"y":319,"style":320},"642.4","after",[37,327],{"x1":328,"y1":329,"x2":330,"y2":329,"stroke":146,"style":331},"280.9","94.0","530.9","stroke-width:2px",[333,334],"polygon",{"points":335,"fill":336},"534.9,94.0 525.9,99.0 525.9,89.0","#5b5cf0",[83,338],{"x":339,"y":340,"width":341,"height":342,"rx":343,"fill":89,"stroke":97,"style":344},"314.3","61.0","187.2","22.0","11","stroke-width:1.2px",[104,346,350],{"x":347,"y":348,"style":349},"407.9","76.0","font-size:11.5px;font-weight:400;fill:var(--brand-strong,#4338ca);text-anchor:middle;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace","cell(r, c) → cell(c, r)",[20,352,354],{"id":353},"step-1-transpose-the-values","Step 1 — Transpose the values",[10,356,357,360,361,364,365,368],{},[32,358,359],{},"iter_rows(values_only=True)"," yields each row as a tuple. ",[32,362,363],{},"zip(*rows)"," regroups those tuples column by column, which is exactly the transpose. Write the result to a new sheet with ",[32,366,367],{},"append",":",[25,370,374],{"className":371,"code":372,"language":373,"meta":30,"style":30},"language-python shiki shiki-themes github-light github-dark-high-contrast","from openpyxl import load_workbook\n\nwb = load_workbook(\"monthly.xlsx\")\nsrc = wb[\"Monthly\"]\nrows = list(src.iter_rows(min_row=1, max_row=4, min_col=1, max_col=5, values_only=True))\nfor new_row in zip(*rows):\n    print(new_row)\n\ndst = wb.create_sheet(\"By month\")\nfor new_row in zip(*rows):\n    dst.append(new_row)\nwb.save(\"monthly_values.xlsx\")\n","python",[32,375,376,392,399,417,434,499,523,532,537,553,570,576],{"__ignoreMap":30},[35,377,378,382,386,389],{"class":37,"line":38},[35,379,381],{"class":380},"s-kum","from",[35,383,385],{"class":384},"skGVy"," openpyxl ",[35,387,388],{"class":380},"import",[35,390,391],{"class":384}," load_workbook\n",[35,393,395],{"class":37,"line":394},2,[35,396,398],{"emptyLinePlaceholder":397},true,"\n",[35,400,402,405,408,411,414],{"class":37,"line":401},3,[35,403,404],{"class":384},"wb ",[35,406,407],{"class":380},"=",[35,409,410],{"class":384}," load_workbook(",[35,412,413],{"class":45},"\"monthly.xlsx\"",[35,415,416],{"class":384},")\n",[35,418,420,423,425,428,431],{"class":37,"line":419},4,[35,421,422],{"class":384},"src ",[35,424,407],{"class":380},[35,426,427],{"class":384}," wb[",[35,429,430],{"class":45},"\"Monthly\"",[35,432,433],{"class":384},"]\n",[35,435,437,440,442,446,449,453,455,457,460,463,465,467,469,472,474,476,478,481,483,486,488,491,493,496],{"class":37,"line":436},5,[35,438,439],{"class":384},"rows ",[35,441,407],{"class":380},[35,443,445],{"class":444},"sP0c6"," list",[35,447,448],{"class":384},"(src.iter_rows(",[35,450,452],{"class":451},"sa561","min_row",[35,454,407],{"class":380},[35,456,142],{"class":444},[35,458,459],{"class":384},", ",[35,461,462],{"class":451},"max_row",[35,464,407],{"class":380},[35,466,85],{"class":444},[35,468,459],{"class":384},[35,470,471],{"class":451},"min_col",[35,473,407],{"class":380},[35,475,142],{"class":444},[35,477,459],{"class":384},[35,479,480],{"class":451},"max_col",[35,482,407],{"class":380},[35,484,485],{"class":444},"5",[35,487,459],{"class":384},[35,489,490],{"class":451},"values_only",[35,492,407],{"class":380},[35,494,495],{"class":444},"True",[35,497,498],{"class":384},"))\n",[35,500,502,505,508,511,514,517,520],{"class":37,"line":501},6,[35,503,504],{"class":380},"for",[35,506,507],{"class":384}," new_row ",[35,509,510],{"class":380},"in",[35,512,513],{"class":444}," zip",[35,515,516],{"class":384},"(",[35,518,519],{"class":380},"*",[35,521,522],{"class":384},"rows):\n",[35,524,526,529],{"class":37,"line":525},7,[35,527,528],{"class":444},"    print",[35,530,531],{"class":384},"(new_row)\n",[35,533,535],{"class":37,"line":534},8,[35,536,398],{"emptyLinePlaceholder":397},[35,538,540,543,545,548,551],{"class":37,"line":539},9,[35,541,542],{"class":384},"dst ",[35,544,407],{"class":380},[35,546,547],{"class":384}," wb.create_sheet(",[35,549,550],{"class":45},"\"By month\"",[35,552,416],{"class":384},[35,554,556,558,560,562,564,566,568],{"class":37,"line":555},10,[35,557,504],{"class":380},[35,559,507],{"class":384},[35,561,510],{"class":380},[35,563,513],{"class":444},[35,565,516],{"class":384},[35,567,519],{"class":380},[35,569,522],{"class":384},[35,571,573],{"class":37,"line":572},11,[35,574,575],{"class":384},"    dst.append(new_row)\n",[35,577,579,582,585],{"class":37,"line":578},12,[35,580,581],{"class":384},"wb.save(",[35,583,584],{"class":45},"\"monthly_values.xlsx\"",[35,586,416],{"class":384},[10,588,589,590,593,594,18],{},"The four source rows of five cells become five rows of four. This is enough when only the numbers matter — feeding another script, say — but the new sheet has lost every font, fill, border and number format: margin shows as ",[32,591,592],{},"0.312"," instead of ",[32,595,596],{},"31.2%",[20,598,600],{"id":599},"step-2-carry-the-formatting-across","Step 2 — Carry the formatting across",[10,602,603,604,607,608,611,612,615],{},"To keep the look, copy each cell's style along with its value, writing source cell ",[32,605,606],{},"(r, c)"," to target cell ",[32,609,610],{},"(c, r)",". Styles in openpyxl are immutable objects shared between cells, so assigning a ",[32,613,614],{},"copy"," of each one is safe:",[25,617,619],{"className":371,"code":618,"language":373,"meta":30,"style":30},"from copy import copy\nfrom openpyxl.utils import get_column_letter\n\ndef transpose_range(src, min_row, max_row, min_col, max_col, dst, top=1, left=1):\n    for r in range(min_row, max_row + 1):\n        for c in range(min_col, max_col + 1):\n            s = src.cell(r, c)\n            t = dst.cell(top + (c - min_col), left + (r - min_row), s.value)\n            if s.has_style:\n                t.font = copy(s.font)\n                t.fill = copy(s.fill)\n                t.border = copy(s.border)\n                t.alignment = copy(s.alignment)\n                t.number_format = s.number_format\n                t.protection = copy(s.protection)\n\nwb = load_workbook(\"monthly.xlsx\")\ndst = wb.create_sheet(\"By month\")\ntranspose_range(wb[\"Monthly\"], 1, 4, 1, 5, dst)\nprint(dst[\"B2\"].value, dst[\"B2\"].number_format, \"|\", dst[\"D3\"].value, dst[\"D3\"].number_format)\n",[32,620,621,633,645,649,675,699,720,730,761,769,779,789,799,810,821,832,837,850,863,891],{"__ignoreMap":30},[35,622,623,625,628,630],{"class":37,"line":38},[35,624,381],{"class":380},[35,626,627],{"class":384}," copy ",[35,629,388],{"class":380},[35,631,632],{"class":384}," copy\n",[35,634,635,637,640,642],{"class":37,"line":394},[35,636,381],{"class":380},[35,638,639],{"class":384}," openpyxl.utils ",[35,641,388],{"class":380},[35,643,644],{"class":384}," get_column_letter\n",[35,646,647],{"class":37,"line":401},[35,648,398],{"emptyLinePlaceholder":397},[35,650,651,654,658,661,663,665,668,670,672],{"class":37,"line":419},[35,652,653],{"class":380},"def",[35,655,657],{"class":656},"s_Opv"," transpose_range",[35,659,660],{"class":384},"(src, min_row, max_row, min_col, max_col, dst, top",[35,662,407],{"class":380},[35,664,142],{"class":444},[35,666,667],{"class":384},", left",[35,669,407],{"class":380},[35,671,142],{"class":444},[35,673,674],{"class":384},"):\n",[35,676,677,680,683,685,688,691,694,697],{"class":37,"line":436},[35,678,679],{"class":380},"    for",[35,681,682],{"class":384}," r ",[35,684,510],{"class":380},[35,686,687],{"class":444}," range",[35,689,690],{"class":384},"(min_row, max_row ",[35,692,693],{"class":380},"+",[35,695,696],{"class":444}," 1",[35,698,674],{"class":384},[35,700,701,704,707,709,711,714,716,718],{"class":37,"line":501},[35,702,703],{"class":380},"        for",[35,705,706],{"class":384}," c ",[35,708,510],{"class":380},[35,710,687],{"class":444},[35,712,713],{"class":384},"(min_col, max_col ",[35,715,693],{"class":380},[35,717,696],{"class":444},[35,719,674],{"class":384},[35,721,722,725,727],{"class":37,"line":525},[35,723,724],{"class":384},"            s ",[35,726,407],{"class":380},[35,728,729],{"class":384}," src.cell(r, c)\n",[35,731,732,735,737,740,742,745,748,751,753,756,758],{"class":37,"line":534},[35,733,734],{"class":384},"            t ",[35,736,407],{"class":380},[35,738,739],{"class":384}," dst.cell(top ",[35,741,693],{"class":380},[35,743,744],{"class":384}," (c ",[35,746,747],{"class":380},"-",[35,749,750],{"class":384}," min_col), left ",[35,752,693],{"class":380},[35,754,755],{"class":384}," (r ",[35,757,747],{"class":380},[35,759,760],{"class":384}," min_row), s.value)\n",[35,762,763,766],{"class":37,"line":539},[35,764,765],{"class":380},"            if",[35,767,768],{"class":384}," s.has_style:\n",[35,770,771,774,776],{"class":37,"line":555},[35,772,773],{"class":384},"                t.font ",[35,775,407],{"class":380},[35,777,778],{"class":384}," copy(s.font)\n",[35,780,781,784,786],{"class":37,"line":572},[35,782,783],{"class":384},"                t.fill ",[35,785,407],{"class":380},[35,787,788],{"class":384}," copy(s.fill)\n",[35,790,791,794,796],{"class":37,"line":578},[35,792,793],{"class":384},"                t.border ",[35,795,407],{"class":380},[35,797,798],{"class":384}," copy(s.border)\n",[35,800,802,805,807],{"class":37,"line":801},13,[35,803,804],{"class":384},"                t.alignment ",[35,806,407],{"class":380},[35,808,809],{"class":384}," copy(s.alignment)\n",[35,811,813,816,818],{"class":37,"line":812},14,[35,814,815],{"class":384},"                t.number_format ",[35,817,407],{"class":380},[35,819,820],{"class":384}," s.number_format\n",[35,822,824,827,829],{"class":37,"line":823},15,[35,825,826],{"class":384},"                t.protection ",[35,828,407],{"class":380},[35,830,831],{"class":384}," copy(s.protection)\n",[35,833,835],{"class":37,"line":834},16,[35,836,398],{"emptyLinePlaceholder":397},[35,838,840,842,844,846,848],{"class":37,"line":839},17,[35,841,404],{"class":384},[35,843,407],{"class":380},[35,845,410],{"class":384},[35,847,413],{"class":45},[35,849,416],{"class":384},[35,851,853,855,857,859,861],{"class":37,"line":852},18,[35,854,542],{"class":384},[35,856,407],{"class":380},[35,858,547],{"class":384},[35,860,550],{"class":45},[35,862,416],{"class":384},[35,864,866,869,871,874,876,878,880,882,884,886,888],{"class":37,"line":865},19,[35,867,868],{"class":384},"transpose_range(wb[",[35,870,430],{"class":45},[35,872,873],{"class":384},"], ",[35,875,142],{"class":444},[35,877,459],{"class":384},[35,879,85],{"class":444},[35,881,459],{"class":384},[35,883,142],{"class":444},[35,885,459],{"class":384},[35,887,485],{"class":444},[35,889,890],{"class":384},", dst)\n",[35,892,894,897,900,903,906,908,911,914,917,920,922,924],{"class":37,"line":893},20,[35,895,896],{"class":444},"print",[35,898,899],{"class":384},"(dst[",[35,901,902],{"class":45},"\"B2\"",[35,904,905],{"class":384},"].value, dst[",[35,907,902],{"class":45},[35,909,910],{"class":384},"].number_format, ",[35,912,913],{"class":45},"\"|\"",[35,915,916],{"class":384},", dst[",[35,918,919],{"class":45},"\"D3\"",[35,921,905],{"class":384},[35,923,919],{"class":45},[35,925,926],{"class":384},"].number_format)\n",[10,928,929,930,934,935,937,938,941,942,945,946,949,950,945,952,955,956,959],{},"Each value keeps its own number format, so after transposing the revenue ",[931,932,933],"em",{},"column"," is currency-style and the margin ",[931,936,933],{}," shows percentages — the formats moved with the cells rather than staying with a row position. The border sides are copied as they are; for a uniform grid that looks right, but a table that has a thick bottom border under its header row will, after transposing, have a thick ",[931,939,940],{},"bottom"," border on the header column's cells, not a thick right border. Swap ",[32,943,944],{},"top","\u002F",[32,947,948],{},"left"," and ",[32,951,940],{},[32,953,954],{},"right"," on the copied ",[32,957,958],{},"Border"," if that matters.",[64,961,73,966,73,969,73,972,73,975,73,982,73,987,73,1027,73,1030,73,1038,73,1041,73,1122,73,1125,73,1129,73,1131,73,1158,73,1161,73,1165,73,1167,73,1188,73,1194,73,1197,73,1200,73,1205,73,1208,73,1212,73,1215,73,1218,73,1220,73,1225,73,1229,73,1234,73,1237,73,1239,73,1243],{"viewBox":962,"role":67,"ariaLabelledBy":963,"xmlns":71,"style":72},"4 0 752 223",[964,965],"tr-code-t","tr-code-d",[75,967,968],{"id":964},"The index swap at the heart of the copy",[79,970,971],{"id":965},"The two lines that read a source cell at row r and column c and write it to row c and column r of the target, followed by the style copies.",[83,973],{"x":85,"y":86,"width":87,"height":974,"fill":89},"223",[83,976],{"x":92,"y":977,"width":978,"height":979,"rx":980,"fill":981,"stroke":97,"style":147},"16.0","720.0","108.0","12","#f0f2f5",[104,983,142],{"x":984,"y":985,"style":986},"60.0","47.0","font-size:11px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace",[104,988,991,996,999,1001,1003,1006,1008,1011,1013,1016,1019,1021,1024],{"x":989,"y":985,"style":990},"82.0","font-size:12.5px;text-anchor:start;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace",[992,993,995],"tspan",{"style":994},"fill:var(--text,#172033);font-weight:400","s",[992,997,998],{"style":994}," ",[992,1000,407],{"style":994},[992,1002,998],{"style":994},[992,1004,1005],{"style":994},"src",[992,1007,18],{"style":994},[992,1009,1010],{"style":994},"cell",[992,1012,516],{"style":994},[992,1014,1015],{"style":994},"r",[992,1017,1018],{"style":994},",",[992,1020,998],{"style":994},[992,1022,1023],{"style":994},"c",[992,1025,1026],{"style":994},")",[104,1028,173],{"x":984,"y":1029,"style":986},"68.0",[1031,1032],"circle",{"cx":140,"cy":1033,"r":1034,"fill":1035,"stroke":1036,"style":1037},"63.5","11.0","#4338ca","none","stroke-width:0px",[104,1039,142],{"x":140,"y":1029,"style":1040},"font-size:12px;font-weight:700;fill:#ffffff;text-anchor:middle",[104,1042,1043,1046,1048,1050,1052,1055,1057,1059,1061,1063,1065,1067,1069,1071,1073,1075,1077,1079,1081,1083,1085,1087,1089,1091,1093,1095,1097,1099,1101,1103,1105,1107,1109,1111,1113,1115,1117,1120],{"x":989,"y":1029,"style":990},[992,1044,1045],{"style":994},"t",[992,1047,998],{"style":994},[992,1049,407],{"style":994},[992,1051,998],{"style":994},[992,1053,1054],{"style":994},"dst",[992,1056,18],{"style":994},[992,1058,1010],{"style":994},[992,1060,516],{"style":994},[992,1062,944],{"style":994},[992,1064,998],{"style":994},[992,1066,693],{"style":994},[992,1068,998],{"style":994},[992,1070,516],{"style":994},[992,1072,1023],{"style":994},[992,1074,998],{"style":994},[992,1076,747],{"style":994},[992,1078,998],{"style":994},[992,1080,471],{"style":994},[992,1082,1026],{"style":994},[992,1084,1018],{"style":994},[992,1086,998],{"style":994},[992,1088,948],{"style":994},[992,1090,998],{"style":994},[992,1092,693],{"style":994},[992,1094,998],{"style":994},[992,1096,516],{"style":994},[992,1098,1015],{"style":994},[992,1100,998],{"style":994},[992,1102,747],{"style":994},[992,1104,998],{"style":994},[992,1106,452],{"style":994},[992,1108,1026],{"style":994},[992,1110,1018],{"style":994},[992,1112,998],{"style":994},[992,1114,995],{"style":994},[992,1116,18],{"style":994},[992,1118,1119],{"style":994},"value",[992,1121,1026],{"style":994},[104,1123,204],{"x":984,"y":1124,"style":986},"89.0",[1031,1126],{"cx":140,"cy":1127,"r":1034,"fill":1128,"stroke":1036,"style":1037},"84.5","#0b6157",[104,1130,173],{"x":140,"y":1124,"style":1040},[104,1132,1133,1135,1137,1140,1142,1144,1146,1148,1150,1152,1154,1156],{"x":989,"y":1124,"style":990},[992,1134,1045],{"style":994},[992,1136,18],{"style":994},[992,1138,1139],{"style":994},"font",[992,1141,998],{"style":994},[992,1143,407],{"style":994},[992,1145,998],{"style":994},[992,1147,614],{"style":994},[992,1149,516],{"style":994},[992,1151,995],{"style":994},[992,1153,18],{"style":994},[992,1155,1139],{"style":994},[992,1157,1026],{"style":994},[104,1159,85],{"x":984,"y":1160,"style":986},"110.0",[1031,1162],{"cx":140,"cy":1163,"r":1034,"fill":1164,"stroke":1036,"style":1037},"105.5","#8a5808",[104,1166,204],{"x":140,"y":1160,"style":1040},[104,1168,1169,1171,1173,1176,1178,1180,1182,1184,1186],{"x":989,"y":1160,"style":990},[992,1170,1045],{"style":994},[992,1172,18],{"style":994},[992,1174,1175],{"style":994},"number_format",[992,1177,998],{"style":994},[992,1179,407],{"style":994},[992,1181,998],{"style":994},[992,1183,995],{"style":994},[992,1185,18],{"style":994},[992,1187,1175],{"style":994},[83,1189],{"x":92,"y":1190,"width":1191,"height":1192,"rx":1193,"fill":145,"stroke":146,"style":147},"138.0","230.7","69.0","10",[1031,1195],{"cx":93,"cy":1196,"r":1034,"fill":1035,"stroke":1036,"style":1037},"172.5",[104,1198,142],{"x":93,"y":1199,"style":1040},"177.0",[104,1201,1204],{"x":984,"y":1202,"style":1203},"160.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","row offset comes from the",[104,1206,1207],{"x":984,"y":1199,"style":1203},"column, column offset from",[104,1209,1211],{"x":984,"y":1210,"style":1203},"194.0","the row",[83,1213],{"x":1214,"y":1190,"width":1191,"height":1192,"rx":1193,"fill":176,"stroke":177,"style":147},"264.7",[1031,1216],{"cx":1217,"cy":1196,"r":1034,"fill":1128,"stroke":1036,"style":1037},"284.7",[104,1219,173],{"x":1217,"y":1199,"style":1040},[104,1221,1224],{"x":1222,"y":1223,"style":1203},"304.7","168.5","styles are copied, not shared",[104,1226,1228],{"x":1222,"y":1227,"style":1203},"185.5","by reference",[83,1230],{"x":1231,"y":1190,"width":1191,"height":1192,"rx":1193,"fill":1232,"stroke":1233,"style":147},"509.3","#fdefd8","var(--gold,#b4740a)",[1031,1235],{"cx":1236,"cy":1196,"r":1034,"fill":1164,"stroke":1036,"style":1037},"529.3",[104,1238,204],{"x":1236,"y":1199,"style":1040},[104,1240,1242],{"x":1241,"y":1223,"style":1203},"549.3","number formats follow the",[104,1244,1119],{"x":1241,"y":1227,"style":1203},[20,1246,1248],{"id":1247},"step-3-swap-column-widths-and-row-heights","Step 3 — Swap column widths and row heights",[10,1250,1251],{},"Widths and heights live on the sheet, not on the cells, so the copy above does not touch them. Column A was 12 wide and row 1 was 22 tall; after transposing, the old header row is the first column and the old first column is the header row. Carry the sizes that make sense across:",[25,1253,1255],{"className":371,"code":1254,"language":373,"meta":30,"style":30},"src = wb[\"Monthly\"]\ndst.column_dimensions[\"A\"].width = max(src.column_dimensions[get_column_letter(c)].width or 8.43 for c in range(1, 6))\nfor c in range(2, 5):\n    dst.column_dimensions[get_column_letter(c)].width = 12\ndst.row_dimensions[1].height = src.row_dimensions[1].height\nwb.save(\"monthly_transposed.xlsx\")\nprint({k: v.width for k, v in dst.column_dimensions.items()})\n",[32,1256,1257,1269,1314,1334,1344,1364,1373],{"__ignoreMap":30},[35,1258,1259,1261,1263,1265,1267],{"class":37,"line":38},[35,1260,422],{"class":384},[35,1262,407],{"class":380},[35,1264,427],{"class":384},[35,1266,430],{"class":45},[35,1268,433],{"class":384},[35,1270,1271,1274,1277,1280,1282,1285,1288,1291,1294,1297,1299,1301,1303,1305,1307,1309,1312],{"class":37,"line":394},[35,1272,1273],{"class":384},"dst.column_dimensions[",[35,1275,1276],{"class":45},"\"A\"",[35,1278,1279],{"class":384},"].width ",[35,1281,407],{"class":380},[35,1283,1284],{"class":444}," max",[35,1286,1287],{"class":384},"(src.column_dimensions[get_column_letter(c)].width ",[35,1289,1290],{"class":380},"or",[35,1292,1293],{"class":444}," 8.43",[35,1295,1296],{"class":380}," for",[35,1298,706],{"class":384},[35,1300,510],{"class":380},[35,1302,687],{"class":444},[35,1304,516],{"class":384},[35,1306,142],{"class":444},[35,1308,459],{"class":384},[35,1310,1311],{"class":444},"6",[35,1313,498],{"class":384},[35,1315,1316,1318,1320,1322,1324,1326,1328,1330,1332],{"class":37,"line":401},[35,1317,504],{"class":380},[35,1319,706],{"class":384},[35,1321,510],{"class":380},[35,1323,687],{"class":444},[35,1325,516],{"class":384},[35,1327,173],{"class":444},[35,1329,459],{"class":384},[35,1331,485],{"class":444},[35,1333,674],{"class":384},[35,1335,1336,1339,1341],{"class":37,"line":419},[35,1337,1338],{"class":384},"    dst.column_dimensions[get_column_letter(c)].width ",[35,1340,407],{"class":380},[35,1342,1343],{"class":444}," 12\n",[35,1345,1346,1349,1351,1354,1356,1359,1361],{"class":37,"line":436},[35,1347,1348],{"class":384},"dst.row_dimensions[",[35,1350,142],{"class":444},[35,1352,1353],{"class":384},"].height ",[35,1355,407],{"class":380},[35,1357,1358],{"class":384}," src.row_dimensions[",[35,1360,142],{"class":444},[35,1362,1363],{"class":384},"].height\n",[35,1365,1366,1368,1371],{"class":37,"line":501},[35,1367,581],{"class":384},[35,1369,1370],{"class":45},"\"monthly_transposed.xlsx\"",[35,1372,416],{"class":384},[35,1374,1375,1377,1380,1382,1385,1387],{"class":37,"line":525},[35,1376,896],{"class":444},[35,1378,1379],{"class":384},"({k: v.width ",[35,1381,504],{"class":380},[35,1383,1384],{"class":384}," k, v ",[35,1386,510],{"class":380},[35,1388,1389],{"class":384}," dst.column_dimensions.items()})\n",[10,1391,1392,1393,1397],{},"A column width is measured in characters and a row height in points, so there is no exact conversion between the two. Set the new widths from the content — the longest value in each new column — as in ",[14,1394,1396],{"href":1395},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fset-column-width-and-row-height-in-openpyxl\u002F","Set Column Width and Row Height in openpyxl",", rather than trying to translate the old heights.",[20,1399,1401],{"id":1400},"step-4-merged-cells","Step 4 — Merged cells",[10,1403,1404],{},"A merged range has to be merged again in the transposed position, with its height and width swapped. Collect the merges inside the source range and re-create them after copying:",[25,1406,1408],{"className":371,"code":1407,"language":373,"meta":30,"style":30},"from openpyxl.worksheet.cell_range import CellRange\n\ndef transposed_merges(src, min_row, max_row, min_col, max_col, top=1, left=1):\n    area = CellRange(min_row=min_row, max_row=max_row, min_col=min_col, max_col=max_col)\n    for m in src.merged_cells.ranges:\n        if m.issubset(area):\n            yield CellRange(min_row=top + m.min_col - min_col, max_row=top + m.max_col - min_col,\n                            min_col=left + m.min_row - min_row, max_col=left + m.max_row - min_row).coord\n\nsrc.merge_cells(\"B1:C1\")\nprint(list(transposed_merges(src, 1, 4, 1, 5)))\n",[32,1409,1410,1422,1426,1448,1486,1498,1506,1546,1582,1586,1596],{"__ignoreMap":30},[35,1411,1412,1414,1417,1419],{"class":37,"line":38},[35,1413,381],{"class":380},[35,1415,1416],{"class":384}," openpyxl.worksheet.cell_range ",[35,1418,388],{"class":380},[35,1420,1421],{"class":384}," CellRange\n",[35,1423,1424],{"class":37,"line":394},[35,1425,398],{"emptyLinePlaceholder":397},[35,1427,1428,1430,1433,1436,1438,1440,1442,1444,1446],{"class":37,"line":401},[35,1429,653],{"class":380},[35,1431,1432],{"class":656}," transposed_merges",[35,1434,1435],{"class":384},"(src, min_row, max_row, min_col, max_col, top",[35,1437,407],{"class":380},[35,1439,142],{"class":444},[35,1441,667],{"class":384},[35,1443,407],{"class":380},[35,1445,142],{"class":444},[35,1447,674],{"class":384},[35,1449,1450,1453,1455,1458,1460,1462,1465,1467,1469,1472,1474,1476,1479,1481,1483],{"class":37,"line":419},[35,1451,1452],{"class":384},"    area ",[35,1454,407],{"class":380},[35,1456,1457],{"class":384}," CellRange(",[35,1459,452],{"class":451},[35,1461,407],{"class":380},[35,1463,1464],{"class":384},"min_row, ",[35,1466,462],{"class":451},[35,1468,407],{"class":380},[35,1470,1471],{"class":384},"max_row, ",[35,1473,471],{"class":451},[35,1475,407],{"class":380},[35,1477,1478],{"class":384},"min_col, ",[35,1480,480],{"class":451},[35,1482,407],{"class":380},[35,1484,1485],{"class":384},"max_col)\n",[35,1487,1488,1490,1493,1495],{"class":37,"line":436},[35,1489,679],{"class":380},[35,1491,1492],{"class":384}," m ",[35,1494,510],{"class":380},[35,1496,1497],{"class":384}," src.merged_cells.ranges:\n",[35,1499,1500,1503],{"class":37,"line":501},[35,1501,1502],{"class":380},"        if",[35,1504,1505],{"class":384}," m.issubset(area):\n",[35,1507,1508,1511,1513,1515,1517,1520,1522,1525,1527,1530,1532,1534,1536,1538,1541,1543],{"class":37,"line":525},[35,1509,1510],{"class":380},"            yield",[35,1512,1457],{"class":384},[35,1514,452],{"class":451},[35,1516,407],{"class":380},[35,1518,1519],{"class":384},"top ",[35,1521,693],{"class":380},[35,1523,1524],{"class":384}," m.min_col ",[35,1526,747],{"class":380},[35,1528,1529],{"class":384}," min_col, ",[35,1531,462],{"class":451},[35,1533,407],{"class":380},[35,1535,1519],{"class":384},[35,1537,693],{"class":380},[35,1539,1540],{"class":384}," m.max_col ",[35,1542,747],{"class":380},[35,1544,1545],{"class":384}," min_col,\n",[35,1547,1548,1551,1553,1556,1558,1561,1563,1566,1568,1570,1572,1574,1577,1579],{"class":37,"line":534},[35,1549,1550],{"class":451},"                            min_col",[35,1552,407],{"class":380},[35,1554,1555],{"class":384},"left ",[35,1557,693],{"class":380},[35,1559,1560],{"class":384}," m.min_row ",[35,1562,747],{"class":380},[35,1564,1565],{"class":384}," min_row, ",[35,1567,480],{"class":451},[35,1569,407],{"class":380},[35,1571,1555],{"class":384},[35,1573,693],{"class":380},[35,1575,1576],{"class":384}," m.max_row ",[35,1578,747],{"class":380},[35,1580,1581],{"class":384}," min_row).coord\n",[35,1583,1584],{"class":37,"line":539},[35,1585,398],{"emptyLinePlaceholder":397},[35,1587,1588,1591,1594],{"class":37,"line":555},[35,1589,1590],{"class":384},"src.merge_cells(",[35,1592,1593],{"class":45},"\"B1:C1\"",[35,1595,416],{"class":384},[35,1597,1598,1600,1602,1605,1608,1610,1612,1614,1616,1618,1620,1622],{"class":37,"line":572},[35,1599,896],{"class":444},[35,1601,516],{"class":384},[35,1603,1604],{"class":444},"list",[35,1606,1607],{"class":384},"(transposed_merges(src, ",[35,1609,142],{"class":444},[35,1611,459],{"class":384},[35,1613,85],{"class":444},[35,1615,459],{"class":384},[35,1617,142],{"class":444},[35,1619,459],{"class":384},[35,1621,485],{"class":444},[35,1623,1624],{"class":384},")))\n",[10,1626,1627,1628,1631,1632,1635,1636,1639],{},"A title merged across ",[32,1629,1630],{},"B1:C1"," — two columns in one row — becomes ",[32,1633,1634],{},"A2:A3",", two rows in one column. Call ",[32,1637,1638],{},"dst.merge_cells(coord)"," for each after the values are in place; only the top-left cell of a merge keeps its value, which is also what Excel's own transpose does.",[20,1641,1643],{"id":1642},"step-5-when-styles-do-not-matter-pandas","Step 5 — When styles do not matter: pandas",[10,1645,1646,1647,1650],{},"For data rather than presentation, pandas transposes a whole sheet in one expression. Read with the first column as the index, take ",[32,1648,1649],{},".T",", and write back:",[25,1652,1654],{"className":371,"code":1653,"language":373,"meta":30,"style":30},"import pandas as pd\n\ndf = pd.read_excel(\"monthly.xlsx\", sheet_name=\"Monthly\", index_col=0)\nflipped = df.T\nflipped.index.name = \"Month\"\nprint(flipped)\nflipped.to_excel(\"monthly_long.xlsx\")\n",[32,1655,1656,1669,1673,1705,1715,1725,1732],{"__ignoreMap":30},[35,1657,1658,1660,1663,1666],{"class":37,"line":38},[35,1659,388],{"class":380},[35,1661,1662],{"class":384}," pandas ",[35,1664,1665],{"class":380},"as",[35,1667,1668],{"class":384}," pd\n",[35,1670,1671],{"class":37,"line":394},[35,1672,398],{"emptyLinePlaceholder":397},[35,1674,1675,1678,1680,1683,1685,1687,1690,1692,1694,1696,1699,1701,1703],{"class":37,"line":401},[35,1676,1677],{"class":384},"df ",[35,1679,407],{"class":380},[35,1681,1682],{"class":384}," pd.read_excel(",[35,1684,413],{"class":45},[35,1686,459],{"class":384},[35,1688,1689],{"class":451},"sheet_name",[35,1691,407],{"class":380},[35,1693,430],{"class":45},[35,1695,459],{"class":384},[35,1697,1698],{"class":451},"index_col",[35,1700,407],{"class":380},[35,1702,86],{"class":444},[35,1704,416],{"class":384},[35,1706,1707,1710,1712],{"class":37,"line":419},[35,1708,1709],{"class":384},"flipped ",[35,1711,407],{"class":380},[35,1713,1714],{"class":384}," df.T\n",[35,1716,1717,1720,1722],{"class":37,"line":436},[35,1718,1719],{"class":384},"flipped.index.name ",[35,1721,407],{"class":380},[35,1723,1724],{"class":45}," \"Month\"\n",[35,1726,1727,1729],{"class":37,"line":501},[35,1728,896],{"class":444},[35,1730,1731],{"class":384},"(flipped)\n",[35,1733,1734,1737,1740],{"class":37,"line":525},[35,1735,1736],{"class":384},"flipped.to_excel(",[35,1738,1739],{"class":45},"\"monthly_long.xlsx\"",[35,1741,416],{"class":384},[10,1743,1744,1745,1748,1749,1752,1753,1756,1757,1760,1761,1764,1765,1769],{},"Look closely at the Orders column: ",[32,1746,1747],{},"1284.0",", not ",[32,1750,1751],{},"1284",". Before the flip, each ",[931,1754,1755],{},"month"," was a column holding revenue, orders and margin together, so pandas stored it as floats; transposing moves those floats into place, and the whole-number column comes out as float. Fix it with ",[32,1758,1759],{},"flipped = flipped.astype({\"Orders\": \"int64\"})",", or call ",[32,1762,1763],{},".infer_objects()"," after reading a sheet with mixed columns. The month labels, which were column headers, become the index, and each metric becomes a column with a single type — which is what charts, pivots and databases want. That shape is closer to the \"one row per record\" layout described in ",[14,1766,1768],{"href":1767},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Funpivot-a-wide-excel-sheet-with-pandas-melt\u002F","Unpivot a Wide Excel Sheet with pandas melt",", which is often what the transpose was really for.",[20,1771,1773],{"id":1772},"step-6-keep-it-linked-with-a-transpose-formula","Step 6 — Keep it linked with a TRANSPOSE formula",[10,1775,1776,1777,1780],{},"Every method above produces a copy: change a number in the source table and the transposed version is stale. If the workbook should keep the two in step, write Excel's ",[32,1778,1779],{},"TRANSPOSE"," function instead, as an array formula over the target range:",[25,1782,1784],{"className":371,"code":1783,"language":373,"meta":30,"style":30},"from openpyxl.worksheet.formula import ArrayFormula\n\nwb = load_workbook(\"monthly.xlsx\")\nws = wb[\"Monthly\"]\nws[\"H1\"] = ArrayFormula(\"H1:K5\", \"=TRANSPOSE(A1:E4)\")\nwb.save(\"monthly_linked.xlsx\")\n",[32,1785,1786,1798,1802,1814,1827,1853],{"__ignoreMap":30},[35,1787,1788,1790,1793,1795],{"class":37,"line":38},[35,1789,381],{"class":380},[35,1791,1792],{"class":384}," openpyxl.worksheet.formula ",[35,1794,388],{"class":380},[35,1796,1797],{"class":384}," ArrayFormula\n",[35,1799,1800],{"class":37,"line":394},[35,1801,398],{"emptyLinePlaceholder":397},[35,1803,1804,1806,1808,1810,1812],{"class":37,"line":401},[35,1805,404],{"class":384},[35,1807,407],{"class":380},[35,1809,410],{"class":384},[35,1811,413],{"class":45},[35,1813,416],{"class":384},[35,1815,1816,1819,1821,1823,1825],{"class":37,"line":419},[35,1817,1818],{"class":384},"ws ",[35,1820,407],{"class":380},[35,1822,427],{"class":384},[35,1824,430],{"class":45},[35,1826,433],{"class":384},[35,1828,1829,1832,1835,1838,1840,1843,1846,1848,1851],{"class":37,"line":436},[35,1830,1831],{"class":384},"ws[",[35,1833,1834],{"class":45},"\"H1\"",[35,1836,1837],{"class":384},"] ",[35,1839,407],{"class":380},[35,1841,1842],{"class":384}," ArrayFormula(",[35,1844,1845],{"class":45},"\"H1:K5\"",[35,1847,459],{"class":384},[35,1849,1850],{"class":45},"\"=TRANSPOSE(A1:E4)\"",[35,1852,416],{"class":384},[35,1854,1855,1857,1860],{"class":37,"line":501},[35,1856,581],{"class":384},[35,1858,1859],{"class":45},"\"monthly_linked.xlsx\"",[35,1861,416],{"class":384},[10,1863,1864],{},"The target range must have the transposed shape — five rows by four columns for a four-by-five source. Excel and LibreOffice calculate it on open; openpyxl does not calculate formulas, so check it by letting LibreOffice recalculate a copy:",[25,1866,1868],{"className":27,"code":1867,"language":29,"meta":30,"style":30},"soffice -env:UserInstallation=file:\u002F\u002F$PWD\u002Flo_profile --headless --convert-to xlsx --outdir recalculated monthly_linked.xlsx > \u002Fdev\u002Fnull 2>&1\nls recalculated\n",[32,1869,1870,1911],{"__ignoreMap":30},[35,1871,1872,1875,1878,1881,1884,1887,1890,1893,1896,1899,1902,1905,1908],{"class":37,"line":38},[35,1873,1874],{"class":41},"soffice",[35,1876,1877],{"class":444}," -env:UserInstallation=file:\u002F\u002F",[35,1879,1880],{"class":384},"$PWD",[35,1882,1883],{"class":444},"\u002Flo_profile",[35,1885,1886],{"class":444}," --headless",[35,1888,1889],{"class":444}," --convert-to",[35,1891,1892],{"class":45}," xlsx",[35,1894,1895],{"class":444}," --outdir",[35,1897,1898],{"class":45}," recalculated",[35,1900,1901],{"class":45}," monthly_linked.xlsx",[35,1903,1904],{"class":380}," >",[35,1906,1907],{"class":45}," \u002Fdev\u002Fnull",[35,1909,1910],{"class":380}," 2>&1\n",[35,1912,1913,1916],{"class":37,"line":394},[35,1914,1915],{"class":41},"ls",[35,1917,1918],{"class":45}," recalculated\n",[25,1920,1922],{"className":371,"code":1921,"language":373,"meta":30,"style":30},"ws = load_workbook(\"recalculated\u002Fmonthly_linked.xlsx\", data_only=True)[\"Monthly\"]\nfor row in ws.iter_rows(min_row=1, max_row=5, min_col=8, max_col=11, values_only=True):\n    print(row)\n",[32,1923,1924,1951,2004],{"__ignoreMap":30},[35,1925,1926,1928,1930,1932,1935,1937,1940,1942,1944,1947,1949],{"class":37,"line":38},[35,1927,1818],{"class":384},[35,1929,407],{"class":380},[35,1931,410],{"class":384},[35,1933,1934],{"class":45},"\"recalculated\u002Fmonthly_linked.xlsx\"",[35,1936,459],{"class":384},[35,1938,1939],{"class":451},"data_only",[35,1941,407],{"class":380},[35,1943,495],{"class":444},[35,1945,1946],{"class":384},")[",[35,1948,430],{"class":45},[35,1950,433],{"class":384},[35,1952,1953,1955,1958,1960,1963,1965,1967,1969,1971,1973,1975,1977,1979,1981,1983,1986,1988,1990,1992,1994,1996,1998,2000,2002],{"class":37,"line":394},[35,1954,504],{"class":380},[35,1956,1957],{"class":384}," row ",[35,1959,510],{"class":380},[35,1961,1962],{"class":384}," ws.iter_rows(",[35,1964,452],{"class":451},[35,1966,407],{"class":380},[35,1968,142],{"class":444},[35,1970,459],{"class":384},[35,1972,462],{"class":451},[35,1974,407],{"class":380},[35,1976,485],{"class":444},[35,1978,459],{"class":384},[35,1980,471],{"class":451},[35,1982,407],{"class":380},[35,1984,1985],{"class":444},"8",[35,1987,459],{"class":384},[35,1989,480],{"class":451},[35,1991,407],{"class":380},[35,1993,343],{"class":444},[35,1995,459],{"class":384},[35,1997,490],{"class":451},[35,1999,407],{"class":380},[35,2001,495],{"class":444},[35,2003,674],{"class":384},[35,2005,2006,2008],{"class":37,"line":401},[35,2007,528],{"class":444},[35,2009,2010],{"class":384},"(row)\n",[10,2012,2013,2014,2016,2017,2020],{},"The formula produces values only — ",[32,2015,1779],{}," does not carry formats — so format the target range once, by column. In Excel 365, ",[32,2018,2019],{},"=TRANSPOSE(A1:E4)"," in a single cell spills automatically; the array formula form above works in every version.",[64,2022,73,2027,73,2030,73,2033,73,2036,73,2041,73,2051,73,2056,73,2060,73,2064,73,2067,73,2070,73,2076,73,2081,73,2086,73,2092,73,2096,73,2101,73,2103,73,2106,73,2110,73,2113,73,2116,73,2123,73,2127,73,2130,73,2132,73,2135,73,2139,73,2142,73,2145,73,2152,73,2156],{"viewBox":2023,"role":67,"ariaLabelledBy":2024,"xmlns":71,"style":72},"4 0 752 272",[2025,2026],"tr-choose-t","tr-choose-d",[75,2028,2029],{"id":2025},"Which transpose?",[79,2031,2032],{"id":2026},"A decision diagram. If the result must stay linked to the source, use a TRANSPOSE array formula. If only the data matters, use pandas .T. If the formatted table must look the same, copy values and styles with openpyxl.",[83,2034],{"x":85,"y":86,"width":87,"height":2035,"fill":89},"272",[83,2037],{"x":2038,"y":977,"width":2039,"height":2040,"rx":980,"fill":145,"stroke":146,"style":331},"216.1","327.8","75.5",[2042,2043,2045],"g",{"transform":2044},"translate(368.0,29.0) scale(1.000)",[2046,2047],"path",{"d":2048,"fill":1036,"stroke":2049,"style":2050},"M4 4h16v16H4z M4 9h16 M4 14h16 M10 4v16","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[104,2052,2055],{"x":2053,"y":2040,"style":2054},"380.0","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","What should the transposed range be?",[37,2057],{"x1":2053,"y1":2058,"x2":2053,"y2":2059,"stroke":146,"style":331},"91.5","111.5",[37,2061],{"x1":2062,"y1":2059,"x2":2063,"y2":2059,"stroke":146,"style":331},"134.7","625.3",[37,2065],{"x1":2062,"y1":2059,"x2":2062,"y2":2066,"stroke":146,"style":331},"157.5",[333,2068],{"points":2069,"fill":336},"134.7,161.5 129.7,152.5 139.7,152.5",[83,2071],{"x":2072,"y":2073,"width":2074,"height":2075,"rx":1193,"fill":89,"stroke":97,"style":344},"78.5","121.5","112.3","21.0",[104,2077,2080],{"x":2062,"y":2078,"style":2079},"136.0","font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","linked to source",[83,2082],{"x":92,"y":2083,"width":2084,"height":2085,"rx":980,"fill":145,"stroke":146,"style":331},"163.5","229.3","93.0",[2042,2087,2089],{"transform":2088},"translate(122.7,176.5) scale(1.000)",[2046,2090],{"d":2091,"fill":1036,"stroke":2049,"style":2050},"M10 14a4 4 0 0 0 5.7 0l3-3a4 4 0 0 0-5.7-5.7l-1 1 M14 10a4 4 0 0 0-5.7 0l-3 3a4 4 0 0 0 5.7 5.7l1-1",[104,2093,2095],{"x":2062,"y":2094,"style":2054},"223.0","TRANSPOSE formula",[104,2097,2100],{"x":2062,"y":2098,"style":2099},"242.5","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","ArrayFormula over the target",[37,2102],{"x1":2053,"y1":2059,"x2":2053,"y2":2066,"stroke":146,"style":331},[333,2104],{"points":2105,"fill":336},"380.0,161.5 375.0,152.5 385.0,152.5",[83,2107],{"x":2108,"y":2073,"width":2109,"height":2075,"rx":1193,"fill":89,"stroke":97,"style":344},"331.9","96.2",[104,2111,2112],{"x":2053,"y":2078,"style":2079},"data for code",[83,2114],{"x":2115,"y":2083,"width":2084,"height":2085,"rx":980,"fill":176,"stroke":177,"style":331},"265.3",[2042,2117,2119],{"transform":2118},"translate(368.0,176.5) scale(1.000)",[2046,2120],{"d":2121,"fill":1036,"stroke":2122,"style":2050},"M3 5h18v14H3z M3 10h18 M3 15h18 M9 5v14","var(--teal-ink,#0b6157)",[104,2124,2126],{"x":2053,"y":2094,"style":2125},"font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","pandas .T",[104,2128,2129],{"x":2053,"y":2098,"style":2099},"read, flip, write",[37,2131],{"x1":2063,"y1":2059,"x2":2063,"y2":2066,"stroke":146,"style":331},[333,2133],{"points":2134,"fill":336},"625.3,161.5 620.3,152.5 630.3,152.5",[83,2136],{"x":2137,"y":2073,"width":2138,"height":2075,"rx":1193,"fill":89,"stroke":97,"style":344},"570.8","109.0",[104,2140,2141],{"x":2063,"y":2078,"style":2079},"formatted copy",[83,2143],{"x":2144,"y":2083,"width":2084,"height":2085,"rx":980,"fill":1232,"stroke":1233,"style":331},"510.7",[2042,2146,2148],{"transform":2147},"translate(613.3,176.5) scale(1.000)",[2046,2149],{"d":2150,"fill":1036,"stroke":2151,"style":2050},"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)",[104,2153,2155],{"x":2063,"y":2094,"style":2154},"font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Copy values + styles",[104,2157,350],{"x":2063,"y":2098,"style":2099},[20,2159,2161],{"id":2160},"common-pitfalls","Common pitfalls",[2163,2164,2165,2173,2191,2197,2210],"ul",{},[2166,2167,2168,2172],"li",{},[2169,2170,2171],"strong",{},"Overlapping source and target."," Transposing in place over the same cells overwrites values before they are read. Read everything first, or write to a new sheet or a clear area.",[2166,2174,2175,2178,2179,2182,2183,2186,2187,2190],{},[2169,2176,2177],{},"Formulas in the source."," Copying a formula string moves it without adjusting its references; ",[32,2180,2181],{},"=B2*1.2"," still points at ",[32,2184,2185],{},"B2",". Load with ",[32,2188,2189],{},"data_only=True"," to copy values, or rewrite references deliberately.",[2166,2192,2193,2196],{},[2169,2194,2195],{},"Borders that suddenly look wrong."," Directional borders keep their side; swap them if the table has a header rule.",[2166,2198,2199,2202,2203,2206,2207,18],{},[2169,2200,2201],{},"Wrong target shape for the array formula."," An ",[32,2204,2205],{},"ArrayFormula"," range smaller than the transposed source truncates it; a larger one fills the spare cells with ",[32,2208,2209],{},"#N\u002FA",[2166,2211,2212,2215],{},[2169,2213,2214],{},"Tables and conditional formats."," An Excel table object or a conditional-format range is not moved by cell copying; re-create them over the new range.",[20,2217,2219],{"id":2218},"conclusion","Conclusion",[10,2221,2222,2223,2225,2226,2228,2229,2231,2232,2234,2235,2237,2238,2240],{},"To transpose values, ",[32,2224,363],{}," over ",[32,2227,359],{},". To keep the look, copy each cell's value and style from ",[32,2230,606],{}," to ",[32,2233,610],{},", then set widths from the new content and re-create merged ranges with their dimensions swapped. Use pandas ",[32,2236,1649],{}," when only the data matters, and a ",[32,2239,1779],{}," array formula when the transposed range should keep following the source.",[20,2242,2244],{"id":2243},"frequently-asked-questions","Frequently asked questions",[10,2246,2247,2250],{},[2169,2248,2249],{},"Does openpyxl have a transpose function?","\nNo. Read the range with iter_rows(values_only=True), regroup it with zip(*rows) and append the new rows to a sheet. To keep formatting, copy each cell's value and style to the swapped position instead.",[10,2252,2253,2256],{},[2169,2254,2255],{},"How do I transpose and keep the formatting?","\nLoop over the source range and write source cell (r, c) to target cell (c, r), copying font, fill, border, alignment, protection and number_format with copy(). Column widths and row heights are sheet settings and must be set separately.",[10,2258,2259,2262,2263,2265],{},[2169,2260,2261],{},"How do I write a TRANSPOSE formula with openpyxl?","\nAssign an ArrayFormula to the top-left target cell: ws",[35,2264,1834],{}," = ArrayFormula(\"H1:K5\", \"=TRANSPOSE(A1:E4)\"). The target range must have the transposed shape. Excel calculates it when the file is opened.",[10,2267,2268,2271],{},[2169,2269,2270],{},"Can pandas transpose an Excel sheet?","\nYes: read it with index_col=0 so the first column becomes the index, call .T and write the result with to_excel. Formatting is not preserved, so use it for data rather than presentation.",[20,2273,2275],{"id":2274},"related","Related",[2163,2277,2278,2284,2291,2298],{},[2166,2279,2280,2281,2283],{},"Up one level: ",[14,2282,17],{"href":16}," — the cell-level toolkit.",[2166,2285,2286,2290],{},[14,2287,2289],{"href":2288},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fmove-a-range-of-cells-with-openpyxl\u002F","Move a Range of Cells with openpyxl"," — shifting a block without turning it.",[2166,2292,2293,2297],{},[14,2294,2296],{"href":2295},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fcopy-cell-styles-with-openpyxl\u002F","Copy Cell Styles with openpyxl"," — the style-copy pattern in detail.",[2166,2299,2300,2304],{},[14,2301,2303],{"href":2302},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Fwrite-dynamic-array-formulas-with-python\u002F","Write Dynamic Array Formulas with Python"," — spilling formulas in Excel 365.",[2306,2307,2308],"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 .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":394,"depth":394,"links":2310},[2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321],{"id":22,"depth":394,"text":23},{"id":353,"depth":394,"text":354},{"id":599,"depth":394,"text":600},{"id":1247,"depth":394,"text":1248},{"id":1400,"depth":394,"text":1401},{"id":1642,"depth":394,"text":1643},{"id":1772,"depth":394,"text":1773},{"id":2160,"depth":394,"text":2161},{"id":2218,"depth":394,"text":2219},{"id":2243,"depth":394,"text":2244},{"id":2274,"depth":394,"text":2275},"2026-09-29","Swap rows and columns in a worksheet from Python: transpose values with zip, carry fonts, fills, borders and number formats across, handle merged cells and column widths, transpose with pandas when styles do not matter, and write a live TRANSPOSE array formula instead of a copy.","md",[2326,2328,2330,2332],{"q":2249,"a":2327},"No. Read the range with iter_rows(values_only=True), regroup it with zip(*rows) and append the new rows to a sheet. To keep formatting, copy each cell's value and style to the swapped position instead.",{"q":2255,"a":2329},"Loop over the source range and write source cell (r, c) to target cell (c, r), copying font, fill, border, alignment, protection and number_format with copy(). Column widths and row heights are sheet settings and must be set separately.",{"q":2261,"a":2331},"Assign an ArrayFormula to the top-left target cell: ws[\"H1\"] = ArrayFormula(\"H1:K5\", \"=TRANSPOSE(A1:E4)\"). The target range must have the transposed shape. Excel calculates it when the file is opened.",{"q":2270,"a":2333},"Yes: read it with index_col=0 so the first column becomes the index, call .T and write the result with to_excel. Formatting is not preserved, so use it for data rather than presentation.","transpose a range of cells with openpyxl",null,{"breadcrumb":2337},[2338,2340,2343],{"name":2339,"item":945},"Home",{"name":2341,"item":2342},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":17,"item":16},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Ftranspose-a-range-of-cells-with-openpyxl",{"title":2346,"description":2347},"Transpose Rows and Columns in Excel with openpyxl","Transpose an Excel range with openpyxl: zip(*rows) for values, copy styles cell by cell, move widths to heights, re-create merges, use pandas .T for data only, or write =TRANSPOSE() as an ArrayFormula that stays linked.","transpose-a-range-of-cells-with-openpyxl","getting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Ftranspose-a-range-of-cells-with-openpyxl\u002Findex",[2351,2352],"openpyxl","messy-sheets","how-to","14DAmBqYjNFMirWZL-Xt2PP_XiYPbIk4qw4bC-QNpRY",[2356,2360],{"title":2357,"path":2358,"stem":2359,"children":-1},"Set Workbook Properties Like Author and Title with Python","\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fset-workbook-properties-with-python","getting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fset-workbook-properties-with-python\u002Findex",{"title":2361,"path":2362,"stem":2363,"children":-1},"Unmerge Cells and Fill the Values with openpyxl","\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Funmerge-cells-and-fill-values-with-openpyxl","getting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Funmerge-cells-and-fill-values-with-openpyxl\u002Findex",[2365,2367],{"path":2366,"title":2341},"\u002Fgetting-started-with-python-excel-automation",{"path":2368,"title":17},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation",[],[2371,2375,2378,2381,2384,2387],{"path":2372,"title":2373,"kind":2374},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl","Applying Conditional Formatting With openpyxl","guide",{"path":2376,"title":2377,"kind":2353},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fadd-data-bars-and-colour-scales-with-openpyxl","Add Data Bars and Colour Scales with openpyxl",{"path":2379,"title":2380,"kind":2353},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fadd-icon-sets-with-openpyxl","Add Icon Sets to Excel Cells with openpyxl",{"path":2382,"title":2383,"kind":2353},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fapply-a-colour-scale-per-row-or-per-column-with-openpyxl","Apply a Colour Scale per Row or per Column with openpyxl",{"path":2385,"title":2386,"kind":2353},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fcontrol-conditional-formatting-rule-order-and-stop-if-true","Control Conditional Formatting Rule Order and Stop If True",{"path":2388,"title":2389,"kind":2353},"\u002Fadvanced-data-transformation-and-cleaning\u002Fapplying-conditional-formatting-with-openpyxl\u002Fhighlight-an-entire-row-based-on-a-cell-value-with-openpyxl","Highlight an Entire Row Based on a Cell Value with openpyxl",1790972070137]