[{"data":1,"prerenderedAt":2390},["ShallowReactive",2],{"doc:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-text-truncated-at-32767-characters-in-excel":3,"surround:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-text-truncated-at-32767-characters-in-excel":2355,"ancestors:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-text-truncated-at-32767-characters-in-excel":2363,"children:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-text-truncated-at-32767-characters-in-excel":2368,"related:\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-text-truncated-at-32767-characters-in-excel":2369},{"id":4,"title":5,"body":6,"dateModified":2322,"datePublished":2322,"description":2323,"extension":2324,"faq":2325,"keyword":2334,"kind":2335,"meta":2336,"navigation":109,"path":2344,"seo":2345,"slug":2348,"stem":2349,"topics":2350,"type":2353,"__hash__":2354},"docs\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-text-truncated-at-32767-characters-in-excel\u002Findex.md","Fix Text Truncated at 32,767 Characters in Excel Output",{"type":7,"value":8,"toc":2309},"minimark",[9,13,24,33,38,67,77,81,84,212,215,222,262,265,269,272,605,620,735,739,742,860,869,1055,1058,1062,1065,1387,1390,1508,1511,1521,1664,1668,1671,2001,2012,2156,2159,2163,2171,2175,2229,2233,2239,2243,2249,2255,2261,2267,2271,2305],[10,11,12],"p",{},"A column of comments, JSON payloads or log excerpts is exported to Excel, and some values come back shorter than they went in. If the export uses pandas you may see this, once, among other output:",[14,15,21],"pre",{"className":16,"code":18,"language":19,"meta":20},[17],"language-text","UserWarning: Cell contents too long (40000), truncated to 32767 characters\n","text","",[22,23,18],"code",{"__ignoreMap":20},[10,25,26,27,32],{},"With openpyxl or xlsxwriter used directly you usually see nothing at all. An Excel cell can hold at most 32,767 characters; every writer enforces that limit, but only pandas mentions it. This page shows what each library does, how to find the long values before they are cut, and three ways to keep the full text. It is part of ",[28,29,31],"a",{"href":30},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002F","Troubleshooting Common Python Excel Errors",".",[34,35,37],"h2",{"id":36},"prerequisites","Prerequisites",[14,39,43],{"className":40,"code":41,"language":42,"meta":20,"style":20},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl xlsxwriter\n","bash",[22,44,45],{"__ignoreMap":20},[46,47,50,54,58,61,64],"span",{"class":48,"line":49},"line",1,[46,51,53],{"class":52},"sMTad","pip",[46,55,57],{"class":56},"srMev"," install",[46,59,60],{"class":56}," pandas",[46,62,63],{"class":56}," openpyxl",[46,65,66],{"class":56}," xlsxwriter\n",[10,68,69,72,73,76],{},[22,70,71],{},"tickets.pkl"," holds five support tickets with a free-text ",[22,74,75],{},"Notes"," column; three of the notes are long conversation histories, as happens when a system appends every message to one field.",[34,78,80],{"id":79},"step-1-find-the-values-that-will-not-fit","Step 1 — Find the values that will not fit",[10,82,83],{},"Measure before writing. The check is cheap and tells you exactly which records and columns are affected:",[14,85,89],{"className":86,"code":87,"language":88,"meta":20,"style":20},"language-python shiki shiki-themes github-light github-dark-high-contrast","LIMIT = 32_767\n\ntickets = pd.read_pickle(\"tickets.pkl\")\nlengths = tickets.select_dtypes(include=[\"object\", \"string\"]).apply(lambda col: col.str.len())\ntoo_long = lengths[lengths.gt(LIMIT).any(axis=1)]\nprint(lengths.max().to_string())\nprint(too_long.to_string())\n","python",[22,90,91,104,111,130,168,195,204],{"__ignoreMap":20},[46,92,93,97,101],{"class":48,"line":49},[46,94,96],{"class":95},"sP0c6","LIMIT",[46,98,100],{"class":99},"s-kum"," =",[46,102,103],{"class":95}," 32_767\n",[46,105,107],{"class":48,"line":106},2,[46,108,110],{"emptyLinePlaceholder":109},true,"\n",[46,112,114,118,121,124,127],{"class":48,"line":113},3,[46,115,117],{"class":116},"skGVy","tickets ",[46,119,120],{"class":99},"=",[46,122,123],{"class":116}," pd.read_pickle(",[46,125,126],{"class":56},"\"tickets.pkl\"",[46,128,129],{"class":116},")\n",[46,131,133,136,138,141,145,147,150,153,156,159,162,165],{"class":48,"line":132},4,[46,134,135],{"class":116},"lengths ",[46,137,120],{"class":99},[46,139,140],{"class":116}," tickets.select_dtypes(",[46,142,144],{"class":143},"sa561","include",[46,146,120],{"class":99},[46,148,149],{"class":116},"[",[46,151,152],{"class":56},"\"object\"",[46,154,155],{"class":116},", ",[46,157,158],{"class":56},"\"string\"",[46,160,161],{"class":116},"]).apply(",[46,163,164],{"class":99},"lambda",[46,166,167],{"class":116}," col: col.str.len())\n",[46,169,171,174,176,179,181,184,187,189,192],{"class":48,"line":170},5,[46,172,173],{"class":116},"too_long ",[46,175,120],{"class":99},[46,177,178],{"class":116}," lengths[lengths.gt(",[46,180,96],{"class":95},[46,182,183],{"class":116},").any(",[46,185,186],{"class":143},"axis",[46,188,120],{"class":99},[46,190,191],{"class":95},"1",[46,193,194],{"class":116},")]\n",[46,196,198,201],{"class":48,"line":197},6,[46,199,200],{"class":95},"print",[46,202,203],{"class":116},"(lengths.max().to_string())\n",[46,205,207,209],{"class":48,"line":206},7,[46,208,200],{"class":95},[46,210,211],{"class":116},"(too_long.to_string())\n",[10,213,214],{},"Three of the five tickets exceed the limit, the longest by more than double: 74,721 characters. Knowing the size of the overshoot matters for the fix: a few values slightly over is a different problem from a column that is routinely ten times too long.",[10,216,217,218,221],{},"Long values rarely come straight from a source system. More often the pipeline builds them: a ",[22,219,220],{},"groupby"," that joins every note per customer into one cell, a column of JSON payloads, an HTML email body, a stack trace pasted into a log field. Aggregations are the usual culprit, because they grow with the data. A summary that was fine in January exceeds the limit by June:",[14,223,225],{"className":86,"code":224,"language":88,"meta":20,"style":20},"per_status = tickets.groupby(\"Status\")[\"Notes\"].agg(\" | \".join)\nprint(per_status.str.len().to_string())\n",[22,226,227,255],{"__ignoreMap":20},[46,228,229,232,234,237,240,243,246,249,252],{"class":48,"line":49},[46,230,231],{"class":116},"per_status ",[46,233,120],{"class":99},[46,235,236],{"class":116}," tickets.groupby(",[46,238,239],{"class":56},"\"Status\"",[46,241,242],{"class":116},")[",[46,244,245],{"class":56},"\"Notes\"",[46,247,248],{"class":116},"].agg(",[46,250,251],{"class":56},"\" | \"",[46,253,254],{"class":116},".join)\n",[46,256,257,259],{"class":48,"line":106},[46,258,200],{"class":95},[46,260,261],{"class":116},"(per_status.str.len().to_string())\n",[10,263,264],{},"Both joined cells are two to three times over the limit. If a report needs \"all notes per group\", that is a sign the notes belong on their own sheet, one row per note, with the group as a column to filter on, rather than concatenated into one cell.",[34,266,268],{"id":267},"step-2-what-each-writer-does","Step 2 — What each writer does",[10,270,271],{},"Write the same DataFrame three ways and measure what is actually in the files:",[14,273,275],{"className":86,"code":274,"language":88,"meta":20,"style":20},"import warnings\nimport xlsxwriter\nfrom openpyxl import Workbook, load_workbook\n\nlong_note = tickets.loc[tickets[\"Ticket\"] == \"T-9005\", \"Notes\"].item()\n\nwb = Workbook()\nwb.active[\"A1\"] = long_note\nwb.save(\"openpyxl.xlsx\")\n\nwbx = xlsxwriter.Workbook(\"xlsxwriter.xlsx\")\nstatus = wbx.add_worksheet().write_string(\"A1\", long_note)\nwbx.close()\n\nwith warnings.catch_warnings(record=True) as caught:\n    warnings.simplefilter(\"always\")\n    tickets.to_excel(\"pandas.xlsx\", index=False)\n\nprint(\"original:\", len(long_note))\nprint(\"openpyxl:\", len(load_workbook(\"openpyxl.xlsx\").active[\"A1\"].value), \"(no warning)\")\nprint(\"xlsxwriter:\", len(load_workbook(\"xlsxwriter.xlsx\").active[\"A1\"].value), \"return value\", status)\nprint(\"pandas:\", len(load_workbook(\"pandas.xlsx\").active[\"C6\"].value), \"warnings:\", len(caught))\n",[22,276,277,285,291,304,308,337,341,351,367,378,383,399,415,421,426,452,463,484,489,508,540,570],{"__ignoreMap":20},[46,278,279,282],{"class":48,"line":49},[46,280,281],{"class":99},"import",[46,283,284],{"class":116}," warnings\n",[46,286,287,289],{"class":48,"line":106},[46,288,281],{"class":99},[46,290,66],{"class":116},[46,292,293,296,299,301],{"class":48,"line":113},[46,294,295],{"class":99},"from",[46,297,298],{"class":116}," openpyxl ",[46,300,281],{"class":99},[46,302,303],{"class":116}," Workbook, load_workbook\n",[46,305,306],{"class":48,"line":132},[46,307,110],{"emptyLinePlaceholder":109},[46,309,310,313,315,318,321,324,327,330,332,334],{"class":48,"line":170},[46,311,312],{"class":116},"long_note ",[46,314,120],{"class":99},[46,316,317],{"class":116}," tickets.loc[tickets[",[46,319,320],{"class":56},"\"Ticket\"",[46,322,323],{"class":116},"] ",[46,325,326],{"class":99},"==",[46,328,329],{"class":56}," \"T-9005\"",[46,331,155],{"class":116},[46,333,245],{"class":56},[46,335,336],{"class":116},"].item()\n",[46,338,339],{"class":48,"line":197},[46,340,110],{"emptyLinePlaceholder":109},[46,342,343,346,348],{"class":48,"line":206},[46,344,345],{"class":116},"wb ",[46,347,120],{"class":99},[46,349,350],{"class":116}," Workbook()\n",[46,352,354,357,360,362,364],{"class":48,"line":353},8,[46,355,356],{"class":116},"wb.active[",[46,358,359],{"class":56},"\"A1\"",[46,361,323],{"class":116},[46,363,120],{"class":99},[46,365,366],{"class":116}," long_note\n",[46,368,370,373,376],{"class":48,"line":369},9,[46,371,372],{"class":116},"wb.save(",[46,374,375],{"class":56},"\"openpyxl.xlsx\"",[46,377,129],{"class":116},[46,379,381],{"class":48,"line":380},10,[46,382,110],{"emptyLinePlaceholder":109},[46,384,386,389,391,394,397],{"class":48,"line":385},11,[46,387,388],{"class":116},"wbx ",[46,390,120],{"class":99},[46,392,393],{"class":116}," xlsxwriter.Workbook(",[46,395,396],{"class":56},"\"xlsxwriter.xlsx\"",[46,398,129],{"class":116},[46,400,402,405,407,410,412],{"class":48,"line":401},12,[46,403,404],{"class":116},"status ",[46,406,120],{"class":99},[46,408,409],{"class":116}," wbx.add_worksheet().write_string(",[46,411,359],{"class":56},[46,413,414],{"class":116},", long_note)\n",[46,416,418],{"class":48,"line":417},13,[46,419,420],{"class":116},"wbx.close()\n",[46,422,424],{"class":48,"line":423},14,[46,425,110],{"emptyLinePlaceholder":109},[46,427,429,432,435,438,440,443,446,449],{"class":48,"line":428},15,[46,430,431],{"class":99},"with",[46,433,434],{"class":116}," warnings.catch_warnings(",[46,436,437],{"class":143},"record",[46,439,120],{"class":99},[46,441,442],{"class":95},"True",[46,444,445],{"class":116},") ",[46,447,448],{"class":99},"as",[46,450,451],{"class":116}," caught:\n",[46,453,455,458,461],{"class":48,"line":454},16,[46,456,457],{"class":116},"    warnings.simplefilter(",[46,459,460],{"class":56},"\"always\"",[46,462,129],{"class":116},[46,464,466,469,472,474,477,479,482],{"class":48,"line":465},17,[46,467,468],{"class":116},"    tickets.to_excel(",[46,470,471],{"class":56},"\"pandas.xlsx\"",[46,473,155],{"class":116},[46,475,476],{"class":143},"index",[46,478,120],{"class":99},[46,480,481],{"class":95},"False",[46,483,129],{"class":116},[46,485,487],{"class":48,"line":486},18,[46,488,110],{"emptyLinePlaceholder":109},[46,490,492,494,497,500,502,505],{"class":48,"line":491},19,[46,493,200],{"class":95},[46,495,496],{"class":116},"(",[46,498,499],{"class":56},"\"original:\"",[46,501,155],{"class":116},[46,503,504],{"class":95},"len",[46,506,507],{"class":116},"(long_note))\n",[46,509,511,513,515,518,520,522,525,527,530,532,535,538],{"class":48,"line":510},20,[46,512,200],{"class":95},[46,514,496],{"class":116},[46,516,517],{"class":56},"\"openpyxl:\"",[46,519,155],{"class":116},[46,521,504],{"class":95},[46,523,524],{"class":116},"(load_workbook(",[46,526,375],{"class":56},[46,528,529],{"class":116},").active[",[46,531,359],{"class":56},[46,533,534],{"class":116},"].value), ",[46,536,537],{"class":56},"\"(no warning)\"",[46,539,129],{"class":116},[46,541,543,545,547,550,552,554,556,558,560,562,564,567],{"class":48,"line":542},21,[46,544,200],{"class":95},[46,546,496],{"class":116},[46,548,549],{"class":56},"\"xlsxwriter:\"",[46,551,155],{"class":116},[46,553,504],{"class":95},[46,555,524],{"class":116},[46,557,396],{"class":56},[46,559,529],{"class":116},[46,561,359],{"class":56},[46,563,534],{"class":116},[46,565,566],{"class":56},"\"return value\"",[46,568,569],{"class":116},", status)\n",[46,571,573,575,577,580,582,584,586,588,590,593,595,598,600,602],{"class":48,"line":572},22,[46,574,200],{"class":95},[46,576,496],{"class":116},[46,578,579],{"class":56},"\"pandas:\"",[46,581,155],{"class":116},[46,583,504],{"class":95},[46,585,524],{"class":116},[46,587,471],{"class":56},[46,589,529],{"class":116},[46,591,592],{"class":56},"\"C6\"",[46,594,534],{"class":116},[46,596,597],{"class":56},"\"warnings:\"",[46,599,155],{"class":116},[46,601,504],{"class":95},[46,603,604],{"class":116},"(caught))\n",[10,606,607,608,611,612,615,616,619],{},"All three store exactly 32,767 characters. openpyxl cuts the string when it is assigned to the cell and says nothing. xlsxwriter's ",[22,609,610],{},"write_string"," returns ",[22,613,614],{},"-2",", which code rarely checks. pandas emits one ",[22,617,618],{},"UserWarning"," per long cell, which scrolls past in a scheduled job's log.",[621,622,630,631,630,635,630,639,630,647,630,656,630,662,630,666,630,670,630,674,630,678,630,683,630,688,630,690,630,693,630,697,630,701,630,704,630,708,630,710,630,712,630,716,630,720,630,723,630,727,630,729,630,731,630,733],"svg",{"viewBox":623,"role":624,"ariaLabelledBy":625,"xmlns":628,"style":629},"225 0 310 144","img",[626,627],"tr-writers-t","tr-writers-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:310px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[632,633,634],"title",{"id":626},"How each writer handles a 74,721-character value",[636,637,638],"desc",{"id":627},"A table of three writers. openpyxl truncates to 32,767 characters silently when the value is assigned. xlsxwriter truncates and returns minus two from write_string. pandas truncates and emits a UserWarning. None raises an error.",[640,641],"rect",{"x":642,"y":643,"width":644,"height":645,"fill":646},"225","0","310","144","#ffffff",[640,648],{"x":649,"y":650,"width":651,"height":652,"rx":643,"fill":653,"stroke":654,"style":655},"241.1","16.0","115.6","28.0","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:1.5px",[19,657,661],{"x":658,"y":659,"style":660},"298.9","35.0","font-size:11px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Writer",[640,663],{"x":664,"y":650,"width":665,"height":652,"rx":643,"fill":653,"stroke":654,"style":655},"356.7","63.5",[19,667,669],{"x":668,"y":659,"style":660},"388.4","Stored",[640,671],{"x":672,"y":650,"width":673,"height":652,"rx":643,"fill":653,"stroke":654,"style":655},"420.2","98.7",[19,675,677],{"x":676,"y":659,"style":660},"469.6","Tells you",[640,679],{"x":649,"y":680,"width":651,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},"44.0","var(--line,#cdd5e6)","stroke-width:1px",[19,684,687],{"x":658,"y":685,"style":686},"63.0","font-size:11px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","openpyxl",[640,689],{"x":664,"y":680,"width":665,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},[19,691,692],{"x":668,"y":685,"style":686},"32,767",[640,694],{"x":672,"y":680,"width":673,"height":652,"rx":643,"fill":695,"stroke":696,"style":655},"#fce9e9","var(--danger,#dc2626)",[19,698,700],{"x":676,"y":685,"style":699},"font-size:11px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","nothing",[640,702],{"x":649,"y":703,"width":651,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},"72.0",[19,705,707],{"x":658,"y":706,"style":686},"91.0","xlsxwriter",[640,709],{"x":664,"y":703,"width":665,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},[19,711,692],{"x":668,"y":706,"style":686},[640,713],{"x":672,"y":703,"width":673,"height":652,"rx":643,"fill":714,"stroke":715,"style":655},"#fdefd8","var(--gold,#b4740a)",[19,717,719],{"x":676,"y":706,"style":718},"font-size:11px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","returns -2",[640,721],{"x":649,"y":722,"width":651,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},"100.0",[19,724,726],{"x":658,"y":725,"style":686},"119.0","pandas to_excel",[640,728],{"x":664,"y":722,"width":665,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},[19,730,692],{"x":668,"y":725,"style":686},[640,732],{"x":672,"y":722,"width":673,"height":652,"rx":643,"fill":714,"stroke":715,"style":655},[19,734,618],{"x":676,"y":725,"style":718},[34,736,738],{"id":737},"step-3-make-truncation-an-error","Step 3 — Make truncation an error",[10,740,741],{},"Losing data silently is the real bug. In pandas, turn that specific warning into an exception for the duration of the export:",[14,743,745],{"className":86,"code":744,"language":88,"meta":20,"style":20},"def to_excel_strict(frame, path, **kwargs):\n    with warnings.catch_warnings():\n        warnings.filterwarnings(\"error\", message=\"Cell contents too long\")\n        frame.to_excel(path, **kwargs)\n\ntry:\n    to_excel_strict(tickets, \"strict.xlsx\", index=False)\nexcept UserWarning as e:\n    print(\"stopped:\", e)\n",[22,746,747,765,773,793,803,807,815,833,847],{"__ignoreMap":20},[46,748,749,752,756,759,762],{"class":48,"line":49},[46,750,751],{"class":99},"def",[46,753,755],{"class":754},"s_Opv"," to_excel_strict",[46,757,758],{"class":116},"(frame, path, ",[46,760,761],{"class":99},"**",[46,763,764],{"class":116},"kwargs):\n",[46,766,767,770],{"class":48,"line":106},[46,768,769],{"class":99},"    with",[46,771,772],{"class":116}," warnings.catch_warnings():\n",[46,774,775,778,781,783,786,788,791],{"class":48,"line":113},[46,776,777],{"class":116},"        warnings.filterwarnings(",[46,779,780],{"class":56},"\"error\"",[46,782,155],{"class":116},[46,784,785],{"class":143},"message",[46,787,120],{"class":99},[46,789,790],{"class":56},"\"Cell contents too long\"",[46,792,129],{"class":116},[46,794,795,798,800],{"class":48,"line":132},[46,796,797],{"class":116},"        frame.to_excel(path, ",[46,799,761],{"class":99},[46,801,802],{"class":116},"kwargs)\n",[46,804,805],{"class":48,"line":170},[46,806,110],{"emptyLinePlaceholder":109},[46,808,809,812],{"class":48,"line":197},[46,810,811],{"class":99},"try",[46,813,814],{"class":116},":\n",[46,816,817,820,823,825,827,829,831],{"class":48,"line":206},[46,818,819],{"class":116},"    to_excel_strict(tickets, ",[46,821,822],{"class":56},"\"strict.xlsx\"",[46,824,155],{"class":116},[46,826,476],{"class":143},[46,828,120],{"class":99},[46,830,481],{"class":95},[46,832,129],{"class":116},[46,834,835,838,841,844],{"class":48,"line":353},[46,836,837],{"class":99},"except",[46,839,840],{"class":95}," UserWarning",[46,842,843],{"class":99}," as",[46,845,846],{"class":116}," e:\n",[46,848,849,852,854,857],{"class":48,"line":369},[46,850,851],{"class":95},"    print",[46,853,496],{"class":116},[46,855,856],{"class":56},"\"stopped:\"",[46,858,859],{"class":116},", e)\n",[10,861,862,863,865,866,868],{},"With openpyxl, check lengths before assigning, as in Step 1; the cut happens on assignment, so there is nothing to check afterwards. With xlsxwriter, wrap ",[22,864,610],{}," so a ",[22,867,614],{}," becomes an exception that names the cell:",[14,870,872],{"className":86,"code":871,"language":88,"meta":20,"style":20},"def write_text(ws, row, col, text):\n    if ws.write_string(row, col, text) == -2:\n        raise ValueError(f\"text in row {row + 1}, column {col + 1} is {len(text):,} characters; the limit is {LIMIT:,}\")\n\nwbx = xlsxwriter.Workbook(\"checked.xlsx\")\nsheet = wbx.add_worksheet()\ntry:\n    write_text(sheet, 4, 2, long_note)\nexcept ValueError as e:\n    print(e)\nfinally:\n    wbx.close()\n",[22,873,874,884,902,979,983,996,1006,1012,1026,1036,1043,1050],{"__ignoreMap":20},[46,875,876,878,881],{"class":48,"line":49},[46,877,751],{"class":99},[46,879,880],{"class":754}," write_text",[46,882,883],{"class":116},"(ws, row, col, text):\n",[46,885,886,889,892,894,897,900],{"class":48,"line":106},[46,887,888],{"class":99},"    if",[46,890,891],{"class":116}," ws.write_string(row, col, text) ",[46,893,326],{"class":99},[46,895,896],{"class":99}," -",[46,898,899],{"class":95},"2",[46,901,814],{"class":116},[46,903,904,907,910,912,915,918,922,925,928,931,934,937,939,942,944,946,948,951,953,955,958,961,963,966,968,970,972,974,977],{"class":48,"line":113},[46,905,906],{"class":99},"        raise",[46,908,909],{"class":95}," ValueError",[46,911,496],{"class":116},[46,913,914],{"class":99},"f",[46,916,917],{"class":56},"\"text in row ",[46,919,921],{"class":920},"sSjpA","{",[46,923,924],{"class":116},"row ",[46,926,927],{"class":99},"+",[46,929,930],{"class":95}," 1",[46,932,933],{"class":920},"}",[46,935,936],{"class":56},", column ",[46,938,921],{"class":920},[46,940,941],{"class":116},"col ",[46,943,927],{"class":99},[46,945,930],{"class":95},[46,947,933],{"class":920},[46,949,950],{"class":56}," is ",[46,952,921],{"class":920},[46,954,504],{"class":95},[46,956,957],{"class":116},"(text)",[46,959,960],{"class":99},":,",[46,962,933],{"class":920},[46,964,965],{"class":56}," characters; the limit is ",[46,967,921],{"class":920},[46,969,96],{"class":95},[46,971,960],{"class":99},[46,973,933],{"class":920},[46,975,976],{"class":56},"\"",[46,978,129],{"class":116},[46,980,981],{"class":48,"line":132},[46,982,110],{"emptyLinePlaceholder":109},[46,984,985,987,989,991,994],{"class":48,"line":170},[46,986,388],{"class":116},[46,988,120],{"class":99},[46,990,393],{"class":116},[46,992,993],{"class":56},"\"checked.xlsx\"",[46,995,129],{"class":116},[46,997,998,1001,1003],{"class":48,"line":197},[46,999,1000],{"class":116},"sheet ",[46,1002,120],{"class":99},[46,1004,1005],{"class":116}," wbx.add_worksheet()\n",[46,1007,1008,1010],{"class":48,"line":206},[46,1009,811],{"class":99},[46,1011,814],{"class":116},[46,1013,1014,1017,1020,1022,1024],{"class":48,"line":353},[46,1015,1016],{"class":116},"    write_text(sheet, ",[46,1018,1019],{"class":95},"4",[46,1021,155],{"class":116},[46,1023,899],{"class":95},[46,1025,414],{"class":116},[46,1027,1028,1030,1032,1034],{"class":48,"line":369},[46,1029,837],{"class":99},[46,1031,909],{"class":95},[46,1033,843],{"class":99},[46,1035,846],{"class":116},[46,1037,1038,1040],{"class":48,"line":380},[46,1039,851],{"class":95},[46,1041,1042],{"class":116},"(e)\n",[46,1044,1045,1048],{"class":48,"line":385},[46,1046,1047],{"class":99},"finally",[46,1049,814],{"class":116},[46,1051,1052],{"class":48,"line":401},[46,1053,1054],{"class":116},"    wbx.close()\n",[10,1056,1057],{},"Failing is the right default for data exports; the next steps are the ways to succeed without losing text.",[34,1059,1061],{"id":1060},"fix-1-split-long-text-across-continuation-cells","Fix 1 — Split long text across continuation cells",[10,1063,1064],{},"If the text must live in the workbook, split it into chunks of at most 32,767 characters, each in its own cell to the right, and mark how many parts there are. Split on whitespace near the boundary so words stay whole:",[14,1066,1068],{"className":86,"code":1067,"language":88,"meta":20,"style":20},"def chunks(text, size=LIMIT):\n    parts = []\n    while len(text) > size:\n        cut = text.rfind(\" \", 0, size)\n        cut = size if cut \u003C= 0 else cut + 1\n        parts.append(text[:cut])\n        text = text[cut:]\n    parts.append(text)\n    return parts\n\nsplit = tickets.copy()\nparts = split[\"Notes\"].map(chunks)\nwidth = parts.map(len).max()\nfor i in range(width):\n    split[f\"Notes part {i + 1}\"] = parts.map(lambda p: p[i] if i \u003C len(p) else \"\")\nsplit[\"Notes parts\"] = parts.map(len)\nsplit = split.drop(columns=\"Notes\")\nto_excel_strict(split, \"split.xlsx\", index=False)\nprint(split[[\"Ticket\", \"Notes parts\"]].to_string(index=False))\n",[22,1069,1070,1087,1097,1114,1134,1165,1170,1180,1185,1193,1197,1207,1222,1237,1254,1308,1326,1344,1362],{"__ignoreMap":20},[46,1071,1072,1074,1077,1080,1082,1084],{"class":48,"line":49},[46,1073,751],{"class":99},[46,1075,1076],{"class":754}," chunks",[46,1078,1079],{"class":116},"(text, size",[46,1081,120],{"class":99},[46,1083,96],{"class":95},[46,1085,1086],{"class":116},"):\n",[46,1088,1089,1092,1094],{"class":48,"line":106},[46,1090,1091],{"class":116},"    parts ",[46,1093,120],{"class":99},[46,1095,1096],{"class":116}," []\n",[46,1098,1099,1102,1105,1108,1111],{"class":48,"line":113},[46,1100,1101],{"class":99},"    while",[46,1103,1104],{"class":95}," len",[46,1106,1107],{"class":116},"(text) ",[46,1109,1110],{"class":99},">",[46,1112,1113],{"class":116}," size:\n",[46,1115,1116,1119,1121,1124,1127,1129,1131],{"class":48,"line":132},[46,1117,1118],{"class":116},"        cut ",[46,1120,120],{"class":99},[46,1122,1123],{"class":116}," text.rfind(",[46,1125,1126],{"class":56},"\" \"",[46,1128,155],{"class":116},[46,1130,643],{"class":95},[46,1132,1133],{"class":116},", size)\n",[46,1135,1136,1138,1140,1143,1146,1149,1152,1155,1158,1160,1162],{"class":48,"line":170},[46,1137,1118],{"class":116},[46,1139,120],{"class":99},[46,1141,1142],{"class":116}," size ",[46,1144,1145],{"class":99},"if",[46,1147,1148],{"class":116}," cut ",[46,1150,1151],{"class":99},"\u003C=",[46,1153,1154],{"class":95}," 0",[46,1156,1157],{"class":99}," else",[46,1159,1148],{"class":116},[46,1161,927],{"class":99},[46,1163,1164],{"class":95}," 1\n",[46,1166,1167],{"class":48,"line":197},[46,1168,1169],{"class":116},"        parts.append(text[:cut])\n",[46,1171,1172,1175,1177],{"class":48,"line":206},[46,1173,1174],{"class":116},"        text ",[46,1176,120],{"class":99},[46,1178,1179],{"class":116}," text[cut:]\n",[46,1181,1182],{"class":48,"line":353},[46,1183,1184],{"class":116},"    parts.append(text)\n",[46,1186,1187,1190],{"class":48,"line":369},[46,1188,1189],{"class":99},"    return",[46,1191,1192],{"class":116}," parts\n",[46,1194,1195],{"class":48,"line":380},[46,1196,110],{"emptyLinePlaceholder":109},[46,1198,1199,1202,1204],{"class":48,"line":385},[46,1200,1201],{"class":116},"split ",[46,1203,120],{"class":99},[46,1205,1206],{"class":116}," tickets.copy()\n",[46,1208,1209,1212,1214,1217,1219],{"class":48,"line":401},[46,1210,1211],{"class":116},"parts ",[46,1213,120],{"class":99},[46,1215,1216],{"class":116}," split[",[46,1218,245],{"class":56},[46,1220,1221],{"class":116},"].map(chunks)\n",[46,1223,1224,1227,1229,1232,1234],{"class":48,"line":417},[46,1225,1226],{"class":116},"width ",[46,1228,120],{"class":99},[46,1230,1231],{"class":116}," parts.map(",[46,1233,504],{"class":95},[46,1235,1236],{"class":116},").max()\n",[46,1238,1239,1242,1245,1248,1251],{"class":48,"line":423},[46,1240,1241],{"class":99},"for",[46,1243,1244],{"class":116}," i ",[46,1246,1247],{"class":99},"in",[46,1249,1250],{"class":95}," range",[46,1252,1253],{"class":116},"(width):\n",[46,1255,1256,1259,1261,1264,1266,1269,1271,1273,1275,1277,1279,1281,1283,1285,1288,1290,1292,1295,1297,1300,1303,1306],{"class":48,"line":428},[46,1257,1258],{"class":116},"    split[",[46,1260,914],{"class":99},[46,1262,1263],{"class":56},"\"Notes part ",[46,1265,921],{"class":920},[46,1267,1268],{"class":116},"i ",[46,1270,927],{"class":99},[46,1272,930],{"class":95},[46,1274,933],{"class":920},[46,1276,976],{"class":56},[46,1278,323],{"class":116},[46,1280,120],{"class":99},[46,1282,1231],{"class":116},[46,1284,164],{"class":99},[46,1286,1287],{"class":116}," p: p[i] ",[46,1289,1145],{"class":99},[46,1291,1244],{"class":116},[46,1293,1294],{"class":99},"\u003C",[46,1296,1104],{"class":95},[46,1298,1299],{"class":116},"(p) ",[46,1301,1302],{"class":99},"else",[46,1304,1305],{"class":56}," \"\"",[46,1307,129],{"class":116},[46,1309,1310,1313,1316,1318,1320,1322,1324],{"class":48,"line":454},[46,1311,1312],{"class":116},"split[",[46,1314,1315],{"class":56},"\"Notes parts\"",[46,1317,323],{"class":116},[46,1319,120],{"class":99},[46,1321,1231],{"class":116},[46,1323,504],{"class":95},[46,1325,129],{"class":116},[46,1327,1328,1330,1332,1335,1338,1340,1342],{"class":48,"line":465},[46,1329,1201],{"class":116},[46,1331,120],{"class":99},[46,1333,1334],{"class":116}," split.drop(",[46,1336,1337],{"class":143},"columns",[46,1339,120],{"class":99},[46,1341,245],{"class":56},[46,1343,129],{"class":116},[46,1345,1346,1349,1352,1354,1356,1358,1360],{"class":48,"line":486},[46,1347,1348],{"class":116},"to_excel_strict(split, ",[46,1350,1351],{"class":56},"\"split.xlsx\"",[46,1353,155],{"class":116},[46,1355,476],{"class":143},[46,1357,120],{"class":99},[46,1359,481],{"class":95},[46,1361,129],{"class":116},[46,1363,1364,1366,1369,1371,1373,1375,1378,1380,1382,1384],{"class":48,"line":491},[46,1365,200],{"class":95},[46,1367,1368],{"class":116},"(split[[",[46,1370,320],{"class":56},[46,1372,155],{"class":116},[46,1374,1315],{"class":56},[46,1376,1377],{"class":116},"]].to_string(",[46,1379,476],{"class":143},[46,1381,120],{"class":99},[46,1383,481],{"class":95},[46,1385,1386],{"class":116},"))\n",[10,1388,1389],{},"Reading it back, join the parts in order and compare with the original:",[14,1391,1393],{"className":86,"code":1392,"language":88,"meta":20,"style":20},"back = pd.read_excel(\"split.xlsx\", keep_default_na=False)\npart_cols = [c for c in back.columns if c.startswith(\"Notes part \")]\nback[\"Notes\"] = back[part_cols].apply(lambda r: \"\".join(r), axis=1)\nprint(\"round trip exact:\", back[\"Notes\"].tolist() == tickets[\"Notes\"].tolist())\n",[22,1394,1395,1418,1448,1481],{"__ignoreMap":20},[46,1396,1397,1400,1402,1405,1407,1409,1412,1414,1416],{"class":48,"line":49},[46,1398,1399],{"class":116},"back ",[46,1401,120],{"class":99},[46,1403,1404],{"class":116}," pd.read_excel(",[46,1406,1351],{"class":56},[46,1408,155],{"class":116},[46,1410,1411],{"class":143},"keep_default_na",[46,1413,120],{"class":99},[46,1415,481],{"class":95},[46,1417,129],{"class":116},[46,1419,1420,1423,1425,1428,1430,1433,1435,1438,1440,1443,1446],{"class":48,"line":106},[46,1421,1422],{"class":116},"part_cols ",[46,1424,120],{"class":99},[46,1426,1427],{"class":116}," [c ",[46,1429,1241],{"class":99},[46,1431,1432],{"class":116}," c ",[46,1434,1247],{"class":99},[46,1436,1437],{"class":116}," back.columns ",[46,1439,1145],{"class":99},[46,1441,1442],{"class":116}," c.startswith(",[46,1444,1445],{"class":56},"\"Notes part \"",[46,1447,194],{"class":116},[46,1449,1450,1453,1455,1457,1459,1462,1464,1467,1470,1473,1475,1477,1479],{"class":48,"line":113},[46,1451,1452],{"class":116},"back[",[46,1454,245],{"class":56},[46,1456,323],{"class":116},[46,1458,120],{"class":99},[46,1460,1461],{"class":116}," back[part_cols].apply(",[46,1463,164],{"class":99},[46,1465,1466],{"class":116}," r: ",[46,1468,1469],{"class":56},"\"\"",[46,1471,1472],{"class":116},".join(r), ",[46,1474,186],{"class":143},[46,1476,120],{"class":99},[46,1478,191],{"class":95},[46,1480,129],{"class":116},[46,1482,1483,1485,1487,1490,1493,1495,1498,1500,1503,1505],{"class":48,"line":132},[46,1484,200],{"class":95},[46,1486,496],{"class":116},[46,1488,1489],{"class":56},"\"round trip exact:\"",[46,1491,1492],{"class":116},", back[",[46,1494,245],{"class":56},[46,1496,1497],{"class":116},"].tolist() ",[46,1499,326],{"class":99},[46,1501,1502],{"class":116}," tickets[",[46,1504,245],{"class":56},[46,1506,1507],{"class":116},"].tolist())\n",[10,1509,1510],{},"The parts column records how many cells belong together, so the reader does not have to guess, and the note in the header row, \"Notes part 1\", tells anyone opening the file in Excel that the text continues to the right. Put the parts on the far right of the sheet, after the columns people filter and sort on, so the long text does not push the useful columns out of view.",[10,1512,1513,1516,1517,1520],{},[22,1514,1515],{},"keep_default_na=False"," matters: without it, empty part cells come back as ",[22,1518,1519],{},"NaN",", and joining fails or inserts the text \"nan\".",[621,1522,630,1528,630,1531,630,1534,630,1539,630,1544,630,1549,630,1553,630,1556,630,1559,630,1563,630,1565,630,1568,630,1571,630,1574,630,1578,630,1582,630,1585,630,1589,630,1593,630,1597,630,1601,630,1605,630,1607,630,1609,630,1611,630,1614,630,1616,630,1618,630,1620,630,1623,630,1627,630,1631,630,1637,630,1641,630,1646,630,1651,630,1658],{"viewBox":1523,"role":624,"ariaLabelledBy":1524,"xmlns":628,"style":1527},"38 0 684 112",[1525,1526],"tr-split-t","tr-split-d","width:100%;max-width:684px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[632,1529,1530],{"id":1525},"One long note becomes three cells",[636,1532,1533],{"id":1526},"On the left a ticket whose notes are 74,721 characters in a single value. On the right the same ticket with Notes part 1, part 2 and part 3, each under the limit, and a column recording that there are three parts.",[640,1535],{"x":1536,"y":643,"width":1537,"height":1538,"fill":646},"38","684","112",[640,1540],{"x":1541,"y":1542,"width":1543,"height":652,"rx":643,"fill":653,"stroke":654,"style":655},"54.3","40.0","67.4",[19,1545,1548],{"x":1546,"y":1547,"style":660},"88.0","59.0","Ticket",[640,1550],{"x":1551,"y":1542,"width":1552,"height":652,"rx":643,"fill":653,"stroke":654,"style":655},"121.7","125.3",[19,1554,75],{"x":1555,"y":1547,"style":660},"184.3",[640,1557],{"x":1541,"y":1558,"width":1543,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},"68.0",[19,1560,1562],{"x":1546,"y":1561,"style":686},"87.0","T-9005",[640,1564],{"x":1551,"y":1558,"width":1552,"height":652,"rx":643,"fill":695,"stroke":696,"style":655},[19,1566,1567],{"x":1555,"y":1561,"style":699},"74,721 characters",[640,1569],{"x":1570,"y":1542,"width":1543,"height":652,"rx":643,"fill":653,"stroke":654,"style":655},"384.7",[19,1572,1548],{"x":1573,"y":1547,"style":660},"418.3",[640,1575],{"x":1576,"y":1542,"width":1577,"height":652,"rx":643,"fill":653,"stroke":654,"style":655},"452.0","71.4",[19,1579,1581],{"x":1580,"y":1547,"style":660},"487.7","Part 1",[640,1583],{"x":1584,"y":1542,"width":1577,"height":652,"rx":643,"fill":653,"stroke":654,"style":655},"523.4",[19,1586,1588],{"x":1587,"y":1547,"style":660},"559.1","Part 2",[640,1590],{"x":1591,"y":1542,"width":1592,"height":652,"rx":643,"fill":653,"stroke":654,"style":655},"594.8","57.3",[19,1594,1596],{"x":1595,"y":1547,"style":660},"623.4","Part 3",[640,1598],{"x":1599,"y":1542,"width":1600,"height":652,"rx":643,"fill":653,"stroke":654,"style":655},"652.1","53.6",[19,1602,1604],{"x":1603,"y":1547,"style":660},"678.9","Parts",[640,1606],{"x":1570,"y":1558,"width":1543,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},[19,1608,1562],{"x":1573,"y":1561,"style":686},[640,1610],{"x":1576,"y":1558,"width":1577,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},[19,1612,1613],{"x":1580,"y":1561,"style":686},"≤32,767",[640,1615],{"x":1584,"y":1558,"width":1577,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},[19,1617,1613],{"x":1587,"y":1561,"style":686},[640,1619],{"x":1591,"y":1558,"width":1592,"height":652,"rx":643,"fill":646,"stroke":681,"style":682},[19,1621,1622],{"x":1595,"y":1561,"style":686},"rest",[640,1624],{"x":1599,"y":1558,"width":1600,"height":652,"rx":643,"fill":1625,"stroke":1626,"style":655},"#d9f4f1","var(--teal,#0f9488)",[19,1628,1630],{"x":1603,"y":1561,"style":1629},"font-size:11px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","3",[19,1632,1636],{"x":1633,"y":1634,"style":1635},"150.6","29.0","font-size:12.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","before",[19,1638,1640],{"x":1639,"y":1634,"style":1635},"545.2","after",[48,1642],{"x1":1643,"y1":1558,"x2":1644,"y2":1558,"stroke":654,"style":1645},"257.0","370.7","stroke-width:2px",[1647,1648],"polygon",{"points":1649,"fill":1650},"374.7,68.0 365.7,73.0 365.7,63.0","#5b5cf0",[640,1652],{"x":1653,"y":659,"width":1654,"height":1655,"rx":1656,"fill":646,"stroke":681,"style":1657},"276.7","78.2","22.0","11","stroke-width:1.2px",[19,1659,1663],{"x":1660,"y":1661,"style":1662},"315.8","50.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","chunks()",[34,1665,1667],{"id":1666},"fix-2-keep-the-full-text-outside-the-workbook","Fix 2 — Keep the full text outside the workbook",[10,1669,1670],{},"Nobody reads 40,000 characters in a spreadsheet cell. Often the better report shows a preview and links to the full text, written alongside the workbook:",[14,1672,1674],{"className":86,"code":1673,"language":88,"meta":20,"style":20},"from pathlib import Path\n\nnotes_dir = Path(\"notes\")\nnotes_dir.mkdir(exist_ok=True)\npreview = tickets[[\"Ticket\", \"Status\"]].copy()\npreview[\"Notes (first 200 chars)\"] = tickets[\"Notes\"].str.slice(0, 200)\npreview[\"Full notes\"] = \"\"\nwith pd.ExcelWriter(\"tickets_with_links.xlsx\", engine=\"xlsxwriter\") as writer:\n    preview.to_excel(writer, index=False, sheet_name=\"Tickets\")\n    ws = writer.sheets[\"Tickets\"]\n    for row, (ticket, text) in enumerate(zip(tickets[\"Ticket\"], tickets[\"Notes\"]), start=1):\n        path = notes_dir \u002F f\"{ticket}.txt\"\n        path.write_text(text, encoding=\"utf-8\")\n        ws.write_url(row, 3, f\"external:{path.as_posix()}\", string=f\"{len(text):,} characters\")\nprint(sorted(p.name for p in notes_dir.iterdir()))\n",[22,1675,1676,1688,1692,1707,1721,1740,1768,1782,1809,1832,1847,1887,1915,1930,1979],{"__ignoreMap":20},[46,1677,1678,1680,1683,1685],{"class":48,"line":49},[46,1679,295],{"class":99},[46,1681,1682],{"class":116}," pathlib ",[46,1684,281],{"class":99},[46,1686,1687],{"class":116}," Path\n",[46,1689,1690],{"class":48,"line":106},[46,1691,110],{"emptyLinePlaceholder":109},[46,1693,1694,1697,1699,1702,1705],{"class":48,"line":113},[46,1695,1696],{"class":116},"notes_dir ",[46,1698,120],{"class":99},[46,1700,1701],{"class":116}," Path(",[46,1703,1704],{"class":56},"\"notes\"",[46,1706,129],{"class":116},[46,1708,1709,1712,1715,1717,1719],{"class":48,"line":132},[46,1710,1711],{"class":116},"notes_dir.mkdir(",[46,1713,1714],{"class":143},"exist_ok",[46,1716,120],{"class":99},[46,1718,442],{"class":95},[46,1720,129],{"class":116},[46,1722,1723,1726,1728,1731,1733,1735,1737],{"class":48,"line":170},[46,1724,1725],{"class":116},"preview ",[46,1727,120],{"class":99},[46,1729,1730],{"class":116}," tickets[[",[46,1732,320],{"class":56},[46,1734,155],{"class":116},[46,1736,239],{"class":56},[46,1738,1739],{"class":116},"]].copy()\n",[46,1741,1742,1745,1748,1750,1752,1754,1756,1759,1761,1763,1766],{"class":48,"line":197},[46,1743,1744],{"class":116},"preview[",[46,1746,1747],{"class":56},"\"Notes (first 200 chars)\"",[46,1749,323],{"class":116},[46,1751,120],{"class":99},[46,1753,1502],{"class":116},[46,1755,245],{"class":56},[46,1757,1758],{"class":116},"].str.slice(",[46,1760,643],{"class":95},[46,1762,155],{"class":116},[46,1764,1765],{"class":95},"200",[46,1767,129],{"class":116},[46,1769,1770,1772,1775,1777,1779],{"class":48,"line":206},[46,1771,1744],{"class":116},[46,1773,1774],{"class":56},"\"Full notes\"",[46,1776,323],{"class":116},[46,1778,120],{"class":99},[46,1780,1781],{"class":56}," \"\"\n",[46,1783,1784,1786,1789,1792,1794,1797,1799,1802,1804,1806],{"class":48,"line":353},[46,1785,431],{"class":99},[46,1787,1788],{"class":116}," pd.ExcelWriter(",[46,1790,1791],{"class":56},"\"tickets_with_links.xlsx\"",[46,1793,155],{"class":116},[46,1795,1796],{"class":143},"engine",[46,1798,120],{"class":99},[46,1800,1801],{"class":56},"\"xlsxwriter\"",[46,1803,445],{"class":116},[46,1805,448],{"class":99},[46,1807,1808],{"class":116}," writer:\n",[46,1810,1811,1814,1816,1818,1820,1822,1825,1827,1830],{"class":48,"line":369},[46,1812,1813],{"class":116},"    preview.to_excel(writer, ",[46,1815,476],{"class":143},[46,1817,120],{"class":99},[46,1819,481],{"class":95},[46,1821,155],{"class":116},[46,1823,1824],{"class":143},"sheet_name",[46,1826,120],{"class":99},[46,1828,1829],{"class":56},"\"Tickets\"",[46,1831,129],{"class":116},[46,1833,1834,1837,1839,1842,1844],{"class":48,"line":380},[46,1835,1836],{"class":116},"    ws ",[46,1838,120],{"class":99},[46,1840,1841],{"class":116}," writer.sheets[",[46,1843,1829],{"class":56},[46,1845,1846],{"class":116},"]\n",[46,1848,1849,1852,1855,1857,1860,1862,1865,1868,1870,1873,1875,1878,1881,1883,1885],{"class":48,"line":385},[46,1850,1851],{"class":99},"    for",[46,1853,1854],{"class":116}," row, (ticket, text) ",[46,1856,1247],{"class":99},[46,1858,1859],{"class":95}," enumerate",[46,1861,496],{"class":116},[46,1863,1864],{"class":95},"zip",[46,1866,1867],{"class":116},"(tickets[",[46,1869,320],{"class":56},[46,1871,1872],{"class":116},"], tickets[",[46,1874,245],{"class":56},[46,1876,1877],{"class":116},"]), ",[46,1879,1880],{"class":143},"start",[46,1882,120],{"class":99},[46,1884,191],{"class":95},[46,1886,1086],{"class":116},[46,1888,1889,1892,1894,1897,1900,1903,1905,1907,1910,1912],{"class":48,"line":401},[46,1890,1891],{"class":116},"        path ",[46,1893,120],{"class":99},[46,1895,1896],{"class":116}," notes_dir ",[46,1898,1899],{"class":99},"\u002F",[46,1901,1902],{"class":99}," f",[46,1904,976],{"class":56},[46,1906,921],{"class":920},[46,1908,1909],{"class":116},"ticket",[46,1911,933],{"class":920},[46,1913,1914],{"class":56},".txt\"\n",[46,1916,1917,1920,1923,1925,1928],{"class":48,"line":417},[46,1918,1919],{"class":116},"        path.write_text(text, ",[46,1921,1922],{"class":143},"encoding",[46,1924,120],{"class":99},[46,1926,1927],{"class":56},"\"utf-8\"",[46,1929,129],{"class":116},[46,1931,1932,1935,1937,1939,1941,1944,1946,1949,1951,1953,1955,1958,1960,1962,1964,1966,1968,1970,1972,1974,1977],{"class":48,"line":423},[46,1933,1934],{"class":116},"        ws.write_url(row, ",[46,1936,1630],{"class":95},[46,1938,155],{"class":116},[46,1940,914],{"class":99},[46,1942,1943],{"class":56},"\"external:",[46,1945,921],{"class":920},[46,1947,1948],{"class":116},"path.as_posix()",[46,1950,933],{"class":920},[46,1952,976],{"class":56},[46,1954,155],{"class":116},[46,1956,1957],{"class":143},"string",[46,1959,120],{"class":99},[46,1961,914],{"class":99},[46,1963,976],{"class":56},[46,1965,921],{"class":920},[46,1967,504],{"class":95},[46,1969,957],{"class":116},[46,1971,960],{"class":99},[46,1973,933],{"class":920},[46,1975,1976],{"class":56}," characters\"",[46,1978,129],{"class":116},[46,1980,1981,1983,1985,1988,1991,1993,1996,1998],{"class":48,"line":428},[46,1982,200],{"class":95},[46,1984,496],{"class":116},[46,1986,1987],{"class":95},"sorted",[46,1989,1990],{"class":116},"(p.name ",[46,1992,1241],{"class":99},[46,1994,1995],{"class":116}," p ",[46,1997,1247],{"class":99},[46,1999,2000],{"class":116}," notes_dir.iterdir()))\n",[10,2002,2003,2004,2007,2008,2011],{},"The ",[22,2005,2006],{},"external:"," prefix makes xlsxwriter write a relative file link, which keeps working when the workbook and the ",[22,2009,2010],{},"notes"," folder are copied or zipped together.",[621,2013,630,2019,630,2022,630,2025,630,2029,630,2035,630,2046,630,2051,630,2055,630,2059,630,2062,630,2065,630,2072,630,2077,630,2083,630,2089,630,2093,630,2098,630,2100,630,2103,630,2107,630,2110,630,2113,630,2120,630,2124,630,2127,630,2129,630,2132,630,2136,630,2139,630,2142,630,2149,630,2153],{"viewBox":2014,"role":624,"ariaLabelledBy":2015,"xmlns":628,"style":2018},"4 0 752 272",[2016,2017],"tr-choose-t","tr-choose-d","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[632,2020,2021],{"id":2016},"Where should the long text go?",[636,2023,2024],{"id":2017},"A decision diagram. If people need the full text inside the workbook, split it into continuation cells. If people only need to see that it exists and open it on demand, show a preview and link to a text file. If a program reads the export, use CSV, JSON Lines or Parquet instead of Excel.",[640,2026],{"x":1019,"y":643,"width":2027,"height":2028,"fill":646},"752","272",[640,2030],{"x":2031,"y":650,"width":2032,"height":2033,"rx":2034,"fill":653,"stroke":654,"style":1645},"240.0","280.0","75.5","12",[2036,2037,2039],"g",{"transform":2038},"translate(368.0,29.0) scale(1.000)",[2040,2041],"path",{"d":2042,"fill":2043,"stroke":2044,"style":2045},"M9 11a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z M2.5 20c0-3.6 2.9-6 6.5-6s6.5 2.4 6.5 6 M16 4.5a3.3 3.3 0 0 1 0 6.3 M18 14.3c2.2.7 3.5 2.8 3.5 5.7","none","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[19,2047,2050],{"x":2048,"y":2033,"style":2049},"380.0","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Who reads the long text?",[48,2052],{"x1":2048,"y1":2053,"x2":2048,"y2":2054,"stroke":654,"style":1645},"91.5","111.5",[48,2056],{"x1":2057,"y1":2054,"x2":2058,"y2":2054,"stroke":654,"style":1645},"134.7","625.3",[48,2060],{"x1":2057,"y1":2054,"x2":2057,"y2":2061,"stroke":654,"style":1645},"157.5",[1647,2063],{"points":2064,"fill":1650},"134.7,161.5 129.7,152.5 139.7,152.5",[640,2066],{"x":2067,"y":2068,"width":2069,"height":2070,"rx":2071,"fill":646,"stroke":681,"style":1657},"54.8","121.5","159.8","21.0","10",[19,2073,2076],{"x":2057,"y":2074,"style":2075},"136.0","font-size:11.5px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:middle","people, in the workbook",[640,2078],{"x":2079,"y":2080,"width":2081,"height":2082,"rx":2034,"fill":653,"stroke":654,"style":1645},"20.0","163.5","229.3","93.0",[2036,2084,2086],{"transform":2085},"translate(122.7,176.5) scale(1.000)",[2040,2087],{"d":2088,"fill":2043,"stroke":2044,"style":2045},"M4 12h6 M10 12l6-6h4 M10 12l6 6h4 M17 3l3 3-3 3 M17 15l3 3-3 3",[19,2090,2092],{"x":2057,"y":2091,"style":2049},"223.0","Split into parts",[19,2094,2097],{"x":2057,"y":2095,"style":2096},"242.5","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","Fix 1",[48,2099],{"x1":2048,"y1":2054,"x2":2048,"y2":2061,"stroke":654,"style":1645},[1647,2101],{"points":2102,"fill":1650},"380.0,161.5 375.0,152.5 385.0,152.5",[640,2104],{"x":2105,"y":2068,"width":2106,"height":2070,"rx":2071,"fill":646,"stroke":681,"style":1657},"314.5","130.9",[19,2108,2109],{"x":2048,"y":2074,"style":2075},"people, on demand",[640,2111],{"x":2112,"y":2080,"width":2081,"height":2082,"rx":2034,"fill":1625,"stroke":1626,"style":1645},"265.3",[2036,2114,2116],{"transform":2115},"translate(368.0,176.5) scale(1.000)",[2040,2117],{"d":2118,"fill":2043,"stroke":2119,"style":2045},"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","var(--teal-ink,#0b6157)",[19,2121,2123],{"x":2048,"y":2091,"style":2122},"font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Preview + link",[19,2125,2126],{"x":2048,"y":2095,"style":2096},"Fix 2",[48,2128],{"x1":2058,"y1":2054,"x2":2058,"y2":2061,"stroke":654,"style":1645},[1647,2130],{"points":2131,"fill":1650},"625.3,161.5 620.3,152.5 630.3,152.5",[640,2133],{"x":2134,"y":2068,"width":2135,"height":2070,"rx":2071,"fill":646,"stroke":681,"style":1657},"586.1","78.4",[19,2137,2138],{"x":2058,"y":2074,"style":2075},"a program",[640,2140],{"x":2141,"y":2080,"width":2081,"height":2082,"rx":2034,"fill":714,"stroke":715,"style":1645},"510.7",[2036,2143,2145],{"transform":2144},"translate(613.3,176.5) scale(1.000)",[2040,2146],{"d":2147,"fill":2043,"stroke":2148,"style":2045},"M9 8l-4 4 4 4 M15 8l4 4-4 4","var(--gold-ink,#7a4e06)",[19,2150,2152],{"x":2058,"y":2091,"style":2151},"font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Another format",[19,2154,2155],{"x":2058,"y":2095,"style":2096},"Fix 3",[10,2157,2158],{},"A preview of the first 200 characters is usually what people scan for anyway: the opening line of a ticket, the error message at the top of a log. Put the length next to it, as the link text does here, so a reader can see at a glance which records are unusually long, which is often a finding in itself: a ticket with 75,000 characters of notes has a story behind it.",[34,2160,2162],{"id":2161},"fix-3-use-a-format-without-the-limit","Fix 3 — Use a format without the limit",[10,2164,2165,2166,2170],{},"If the consumer is another program rather than a person, Excel is the wrong container for long text. CSV, JSON Lines and Parquet have no per-value limit. Beware that opening a CSV in Excel applies the same 32,767-character cell limit on display, so the file must be read by code, not double-clicked. ",[28,2167,2169],{"href":2168},"\u002Fgetting-started-with-python-excel-automation\u002Fchoosing-a-python-excel-library\u002Fexcel-vs-csv-vs-parquet-for-python-data-pipelines\u002F","Excel vs CSV vs Parquet for Python Data Pipelines"," compares the options.",[34,2172,2174],{"id":2173},"common-pitfalls","Common pitfalls",[2176,2177,2178,2189,2200,2206,2215],"ul",{},[2179,2180,2181,2185,2186,2188],"li",{},[2182,2183,2184],"strong",{},"Ignoring pandas warnings."," One ",[22,2187,618],{}," per cell is easy to miss; make it an error.",[2179,2190,2191,2196,2197,2199],{},[2182,2192,2193,2194,32],{},"Not checking ",[22,2195,610],{}," A return value of ",[22,2198,614],{}," means the text was cut.",[2179,2201,2202,2205],{},[2182,2203,2204],{},"Splitting mid-word or mid-character."," Split at whitespace; the round-trip check proves nothing was lost.",[2179,2207,2208,2211,2212,2214],{},[2182,2209,2210],{},"Reading chunks back with NaN."," Use ",[22,2213,1515],{}," so empty parts are empty strings.",[2179,2216,2217,2220,2221,2224,2225,2228],{},[2182,2218,2219],{},"Formulas have their own limit."," Formula text is limited to 8,192 characters; long ",[22,2222,2223],{},"CONCAT"," or ",[22,2226,2227],{},"IF"," chains hit that first.",[34,2230,2232],{"id":2231},"conclusion","Conclusion",[10,2234,2235,2236,2238],{},"Excel cells hold 32,767 characters and every Python writer truncates longer text: openpyxl silently, xlsxwriter with a ",[22,2237,614],{}," return, pandas with a warning. Measure string lengths before writing and turn truncation into an error, then keep the full text by splitting it into continuation cells that reassemble exactly, by writing previews that link to text files, or by using a format without the limit when the reader is a program.",[34,2240,2242],{"id":2241},"frequently-asked-questions","Frequently asked questions",[10,2244,2245,2248],{},[2182,2246,2247],{},"What is the maximum number of characters in an Excel cell?","\n32,767 characters. Excel shows only the first 1,024 or so in the cell itself, but stores and edits up to the limit.",[10,2250,2251,2254],{},[2182,2252,2253],{},"Why is my text cut off when I write it with openpyxl?","\nopenpyxl truncates strings longer than 32,767 characters when they are assigned to a cell, without a warning. Check lengths before writing.",[10,2256,2257,2260],{},[2182,2258,2259],{},"How do I make pandas fail instead of truncating long text?","\nWrap to_excel in warnings.catch_warnings() with warnings.filterwarnings(\"error\", message=\"Cell contents too long\"), so the truncation warning is raised as an exception.",[10,2262,2263,2266],{},[2182,2264,2265],{},"How do I store text longer than 32,767 characters in Excel?","\nSplit it into chunks across several cells and join them when reading, or keep the full text in separate files and link to them from the workbook.",[34,2268,2270],{"id":2269},"related","Related",[2176,2272,2273,2279,2286,2291,2298],{},[2179,2274,2275,2276,2278],{},"Up one level: ",[28,2277,31],{"href":30}," — the other common errors.",[2179,2280,2281,2285],{},[28,2282,2284],{"href":2283},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-illegalcharactererror-when-writing-excel-with-openpyxl\u002F","Fix IllegalCharacterError When Writing Excel with openpyxl"," — the other text value that fails on write.",[2179,2287,2288,2290],{},[28,2289,2169],{"href":2168}," — formats without the limit.",[2179,2292,2293,2297],{},[28,2294,2296],{"href":2295},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-this-sheet-is-too-large-error\u002F","Fix \"This sheet is too large\" When Writing Excel with pandas"," — Excel's row and column limits.",[2179,2299,2300,2304],{},[28,2301,2303],{"href":2302},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fadd-hyperlinks-to-excel-cells-with-python\u002F","Add Hyperlinks to Excel Cells with Python"," — links in reports.",[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 .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}",{"title":20,"searchDepth":106,"depth":106,"links":2310},[2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321],{"id":36,"depth":106,"text":37},{"id":79,"depth":106,"text":80},{"id":267,"depth":106,"text":268},{"id":737,"depth":106,"text":738},{"id":1060,"depth":106,"text":1061},{"id":1666,"depth":106,"text":1667},{"id":2161,"depth":106,"text":2162},{"id":2173,"depth":106,"text":2174},{"id":2231,"depth":106,"text":2232},{"id":2241,"depth":106,"text":2242},{"id":2269,"depth":106,"text":2270},"2026-09-29","An Excel cell holds at most 32,767 characters, and Python writers enforce it differently: openpyxl cuts long text silently, xlsxwriter returns -2, pandas warns. Find the long values before writing, make truncation an error, and keep the full text by splitting it across cells, linking to a file, or choosing another format.","md",[2326,2328,2330,2332],{"q":2247,"a":2327},"32,767 characters. Excel shows only the first 1,024 or so in the cell itself, but stores and edits up to the limit.",{"q":2253,"a":2329},"openpyxl truncates strings longer than 32,767 characters when they are assigned to a cell, without a warning. Check lengths before writing.",{"q":2259,"a":2331},"Wrap to_excel in warnings.catch_warnings() with warnings.filterwarnings(\"error\", message=\"Cell contents too long\"), so the truncation warning is raised as an exception.",{"q":2265,"a":2333},"Split it into chunks across several cells and join them when reading, or keep the full text in separate files and link to them from the workbook.","fix text truncated at 32767 characters in excel",null,{"breadcrumb":2337},[2338,2340,2343],{"name":2339,"item":1899},"Home",{"name":2341,"item":2342},"Getting Started with Python Excel Automation","\u002Fgetting-started-with-python-excel-automation\u002F",{"name":31,"item":30},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-text-truncated-at-32767-characters-in-excel",{"title":2346,"description":2347},"Fix Text Truncated at 32767 Characters in Excel from Python","Why long text is cut to 32,767 characters when writing Excel with openpyxl, xlsxwriter or pandas, how to find long values, turn silent truncation into an error, split text into chunks and reassemble it, or link to full text.","fix-text-truncated-at-32767-characters-in-excel","getting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-text-truncated-at-32767-characters-in-excel\u002Findex",[2351,2352],"troubleshooting","writing-excel","how-to","3h0e_wVsra8ngz-ildwcy5hhnraEQLF3bOC5UnXKVgM",[2356,2360],{"title":2357,"path":2358,"stem":2359,"children":-1},"Fix \"Sheet Already Exists\" Errors in pandas ExcelWriter","\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-sheet-already-exists-errors-in-pandas-excelwriter","getting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-sheet-already-exists-errors-in-pandas-excelwriter\u002Findex",{"title":2296,"path":2361,"stem":2362,"children":-1},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-this-sheet-is-too-large-error","getting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-this-sheet-is-too-large-error\u002Findex",[2364,2366],{"path":2365,"title":2341},"\u002Fgetting-started-with-python-excel-automation",{"path":2367,"title":31},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors",[],[2370,2374,2377,2380,2383,2386],{"path":2371,"title":2372,"kind":2373},"\u002Fautomating-reporting-workflows\u002Ferror-handling-and-logging-in-excel-automation\u002Fhandle-permission-denied-when-writing-excel-in-python","Handle Permission Denied When Writing Excel in Python","fix",{"path":2375,"title":2376,"kind":2353},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fwhat-openpyxl-loses-when-saving-an-existing-workbook","What openpyxl Loses When You Save an Existing Workbook",{"path":2378,"title":2379,"kind":2373},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Ffix-excel-serial-numbers-showing-instead-of-dates","Fix Excel Serial Numbers Showing Instead of Dates",{"path":2381,"title":2382,"kind":2353},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fhandle-daylight-saving-time-in-excel-timestamps","Handle Daylight Saving Time in Excel Timestamps",{"path":2384,"title":2385,"kind":2353},"\u002Fautomating-reporting-workflows\u002Fautomating-excel-online-with-microsoft-graph\u002Fhandle-microsoft-graph-throttling-for-excel","Handle Microsoft Graph Throttling in Excel Automation",{"path":2387,"title":2388,"kind":2389},"\u002Fautomating-reporting-workflows\u002Ferror-handling-and-logging-in-excel-automation","Error Handling and Logging in Excel Automation","guide",1790972067479]