[{"data":1,"prerenderedAt":2317},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fremove-hidden-data-before-sharing-an-excel-file":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fremove-hidden-data-before-sharing-an-excel-file":2284,"ancestors:\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fremove-hidden-data-before-sharing-an-excel-file":2293,"children:\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fremove-hidden-data-before-sharing-an-excel-file":2298,"related:\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fremove-hidden-data-before-sharing-an-excel-file":2299},{"id":4,"title":5,"body":6,"dateModified":2250,"datePublished":2250,"description":2251,"extension":2252,"faq":2253,"keyword":2262,"kind":2263,"meta":2264,"navigation":296,"path":2273,"seo":2274,"slug":2277,"stem":2278,"topics":2279,"type":2282,"__hash__":2283},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fremove-hidden-data-before-sharing-an-excel-file\u002Findex.md","Remove Hidden Data Before Sharing an Excel File",{"type":7,"value":8,"toc":2238},"minimark",[9,24,213,218,244,253,257,260,1052,1059,1297,1301,1308,1778,1796,1800,1803,1942,1945,2058,2062,2095,2099,2153,2157,2160,2164,2173,2177,2183,2189,2195,2201,2205,2234],[10,11,12,13,17,18,23],"p",{},"Hiding is a layout tool, not a privacy tool. A workbook that looks clean on screen can carry a hidden sheet of workings, a ",[14,15,16],"em",{},"very hidden"," salary sheet that does not even appear in Excel's Unhide menu, columns of cost prices someone hid before the meeting, comments with names and opinions in them, and formulas that point straight at all of the above. Sent to a customer or a supplier, every one of those travels with the file, and anyone can reveal them in seconds. This page, part of ",[19,20,22],"a",{"href":21},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002F","Protecting and Sharing Excel Workbooks",", audits a workbook for hidden data with openpyxl and builds a clean, values-only copy to share instead.",[25,26,34,35,34,39,34,43,34,51,34,61,34,72,34,79,34,84,34,92,34,99,34,105,34,110,34,113,34,118,34,121,34,127,34,131,34,135,34,138,34,141,34,146,34,153,34,157,34,161,34,164,34,167,34,170,34,176,34,180,34,184,34,187,34,190,34,193,34,199,34,203,34,207,34,210],"svg",{"viewBox":27,"role":28,"ariaLabelledBy":29,"xmlns":32,"style":33},"4 0 752 540","img",[30,31],"hid-kinds-t","hid-kinds-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  ",[36,37,38],"title",{"id":30},"Where hidden data hides in a workbook",[40,41,42],"desc",{"id":31},"A workbook fans out to six places data can hide. Sheets that are hidden or very hidden. Rows and columns that are hidden, and cells formatted with ;;; so their values do not display. Comments and notes carrying names and remarks. Formulas and defined names that reference hidden sheets. Links to other files. Document properties such as the author and last editor.",[44,45],"rect",{"x":46,"y":47,"width":48,"height":49,"fill":50},"4","0","752","540","#ffffff",[44,52],{"x":53,"y":54,"width":55,"height":56,"rx":57,"fill":58,"stroke":59,"style":60},"20.0","223.5","220.0","93.0","12","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:2px",[62,63,65],"g",{"transform":64},"translate(118.0,236.5) scale(1.000)",[66,67],"path",{"d":68,"fill":69,"stroke":70,"style":71},"M6 3h9l4 4v14H6z M15 3v4h4 M9.5 11.5l4.5 6 M14 11.5l-4.5 6","none","var(--brand-strong,#4338ca)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[73,74,78],"text",{"x":75,"y":76,"style":77},"130.0","283.0","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","q3_results.xlsx",[73,80,83],{"x":75,"y":81,"style":82},"302.5","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","looks like one clean sheet",[44,85],{"x":86,"y":87,"width":88,"height":89,"rx":57,"fill":90,"stroke":91,"style":60},"490.0","16.0","250.0","92.0","#fee8f2","var(--accent,#f43f8f)",[62,93,95],{"transform":94},"translate(603.0,29.0) scale(1.000)",[66,96],{"d":97,"fill":69,"stroke":98,"style":71},"M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12z M12 9a3 3 0 1 0 .01 0z","var(--accent-ink,#be185d)",[73,100,104],{"x":101,"y":102,"style":103},"615.0","75.0","font-size:13px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","Hidden sheets",[73,106,109],{"x":101,"y":107,"style":108},"94.0","font-size:11px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","hidden, veryHidden",[66,111],{"d":112,"fill":69,"stroke":59,"style":60},"M244.0,270.0 C364.0,270.0 364.0,62.0 480.0,62.0",[114,115],"polygon",{"points":116,"fill":117},"484.0,62.0 475.0,67.0 475.0,57.0","#5b5cf0",[44,119],{"x":86,"y":120,"width":88,"height":89,"rx":57,"fill":90,"stroke":91,"style":60},"120.0",[62,122,124],{"transform":123},"translate(603.0,133.0) scale(1.000)",[66,125],{"d":126,"fill":69,"stroke":98,"style":71},"M3 5h18v14H3z M3 10h18 M3 15h18 M9 5v14",[73,128,130],{"x":101,"y":129,"style":103},"179.0","Hidden rows and columns",[73,132,134],{"x":101,"y":133,"style":108},"198.0","plus ;;; formats",[66,136],{"d":137,"fill":69,"stroke":59,"style":60},"M244.0,270.0 C364.0,270.0 364.0,166.0 480.0,166.0",[114,139],{"points":140,"fill":117},"484.0,166.0 475.0,171.0 475.0,161.0",[44,142],{"x":86,"y":143,"width":88,"height":89,"rx":57,"fill":144,"stroke":145,"style":60},"224.0","#fdefd8","var(--gold,#b4740a)",[62,147,149],{"transform":148},"translate(603.0,237.0) scale(1.000)",[66,150],{"d":151,"fill":69,"stroke":152,"style":71},"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","var(--gold-ink,#7a4e06)",[73,154,156],{"x":101,"y":76,"style":155},"font-size:13px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Comments",[73,158,160],{"x":101,"y":159,"style":108},"302.0","authors and remarks",[66,162],{"d":163,"fill":69,"stroke":59,"style":60},"M244.0,270.0 C364.0,270.0 364.0,270.0 480.0,270.0",[114,165],{"points":166,"fill":117},"484.0,270.0 475.0,275.0 475.0,265.0",[44,168],{"x":86,"y":169,"width":88,"height":89,"rx":57,"fill":144,"stroke":145,"style":60},"328.0",[62,171,173],{"transform":172},"translate(603.0,341.0) scale(1.000)",[66,174],{"d":175,"fill":69,"stroke":152,"style":71},"M9 8l-4 4 4 4 M15 8l4 4-4 4",[73,177,179],{"x":101,"y":178,"style":155},"387.0","Formulas and names",[73,181,183],{"x":101,"y":182,"style":108},"406.0","point at hidden sheets",[66,185],{"d":186,"fill":69,"stroke":59,"style":60},"M244.0,270.0 C364.0,270.0 364.0,374.0 480.0,374.0",[114,188],{"points":189,"fill":117},"484.0,374.0 475.0,379.0 475.0,369.0",[44,191],{"x":86,"y":192,"width":88,"height":89,"rx":57,"fill":144,"stroke":145,"style":60},"432.0",[62,194,196],{"transform":195},"translate(603.0,445.0) scale(1.000)",[66,197],{"d":198,"fill":69,"stroke":152,"style":71},"M6 3h9l4 4v14H6z M15 3v4h4",[73,200,202],{"x":101,"y":201,"style":155},"491.0","Properties",[73,204,206],{"x":101,"y":205,"style":108},"510.0","author and title",[66,208],{"d":209,"fill":69,"stroke":59,"style":60},"M244.0,270.0 C364.0,270.0 364.0,478.0 480.0,478.0",[114,211],{"points":212,"fill":117},"484.0,478.0 475.0,483.0 475.0,473.0",[214,215,217],"h2",{"id":216},"prerequisites","Prerequisites",[219,220,225],"pre",{"className":221,"code":222,"language":223,"meta":224,"style":224},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install openpyxl\n","bash","",[226,227,228],"code",{"__ignoreMap":224},[229,230,233,237,241],"span",{"class":231,"line":232},"line",1,[229,234,236],{"class":235},"sMTad","pip",[229,238,240],{"class":239},"srMev"," install",[229,242,243],{"class":239}," openpyxl\n",[10,245,246,248,249,252],{},[226,247,78],{}," shows one sheet, Summary, with revenue and margin by region. Behind it are a hidden Workings sheet, a very hidden Salaries sheet, a hidden column of cost prices, a hidden draft note, a cell whose value is concealed with a ",[226,250,251],{},";;;"," format, a comment, a hidden defined name and internal document properties. It was last saved by a spreadsheet application, so its formulas have calculated values stored with them.",[214,254,256],{"id":255},"step-1-audit-the-workbook","Step 1 — Audit the workbook",[10,258,259],{},"Collect everything that is present but not visible into one list of findings. Each check is short; together they cover what a reader could uncover:",[219,261,265],{"className":262,"code":263,"language":264,"meta":224,"style":224},"language-python shiki shiki-themes github-light github-dark-high-contrast","import re\nfrom openpyxl import load_workbook\n\ndef audit(path):\n    wb = load_workbook(path)\n    found = []\n    for ws in wb.worksheets:\n        if ws.sheet_state != \"visible\":\n            found.append((\"sheet\", ws.title, f\"{ws.sheet_state}, {ws.max_row} rows\"))\n        for letter, dim in ws.column_dimensions.items():\n            if dim.hidden and any(c.value is not None for c in ws[letter]):\n                found.append((\"hidden column\", f\"{ws.title}!{letter}\", \"contains data\"))\n        for idx, dim in ws.row_dimensions.items():\n            if dim.hidden and any(c.value is not None for c in ws[idx]):\n                found.append((\"hidden row\", f\"{ws.title}!{idx}\", \"contains data\"))\n        for row in ws.iter_rows():\n            for c in row:\n                if c.comment:\n                    found.append((\"comment\", f\"{ws.title}!{c.coordinate}\", f\"by {c.comment.author}\"))\n                if c.number_format == \";;;\" and c.value is not None:\n                    found.append((\"concealed value\", f\"{ws.title}!{c.coordinate}\", \"format ;;;\"))\n                if isinstance(c.value, str) and c.value.startswith(\"=\") and \"!\" in c.value:\n                    found.append((\"cross-sheet formula\", f\"{ws.title}!{c.coordinate}\", c.value))\n    for name, dn in wb.defined_names.items():\n        found.append((\"defined name\", name, f\"{dn.attr_text}{' (hidden)' if dn.hidden else ''}\"))\n    if wb._external_links:\n        found.append((\"external links\", str(len(wb._external_links)), \"links to other files\"))\n    for field in (\"creator\", \"lastModifiedBy\", \"title\", \"subject\", \"keywords\", \"description\"):\n        value = getattr(wb.properties, field)\n        if value:\n            found.append((\"property\", field, value))\n    return found\n\nfor kind, where, detail in audit(\"q3_results.xlsx\"):\n    print(f\"{kind:20} {where:14} {detail}\")\n","python",[226,266,267,277,291,298,311,323,334,349,367,411,425,464,505,518,546,583,596,609,618,668,696,733,771,804,817,862,871,897,941,955,963,974,983,988,1007],{"__ignoreMap":224},[229,268,269,273],{"class":231,"line":232},[229,270,272],{"class":271},"s-kum","import",[229,274,276],{"class":275},"skGVy"," re\n",[229,278,280,283,286,288],{"class":231,"line":279},2,[229,281,282],{"class":271},"from",[229,284,285],{"class":275}," openpyxl ",[229,287,272],{"class":271},[229,289,290],{"class":275}," load_workbook\n",[229,292,294],{"class":231,"line":293},3,[229,295,297],{"emptyLinePlaceholder":296},true,"\n",[229,299,301,304,308],{"class":231,"line":300},4,[229,302,303],{"class":271},"def",[229,305,307],{"class":306},"s_Opv"," audit",[229,309,310],{"class":275},"(path):\n",[229,312,314,317,320],{"class":231,"line":313},5,[229,315,316],{"class":275},"    wb ",[229,318,319],{"class":271},"=",[229,321,322],{"class":275}," load_workbook(path)\n",[229,324,326,329,331],{"class":231,"line":325},6,[229,327,328],{"class":275},"    found ",[229,330,319],{"class":271},[229,332,333],{"class":275}," []\n",[229,335,337,340,343,346],{"class":231,"line":336},7,[229,338,339],{"class":271},"    for",[229,341,342],{"class":275}," ws ",[229,344,345],{"class":271},"in",[229,347,348],{"class":275}," wb.worksheets:\n",[229,350,352,355,358,361,364],{"class":231,"line":351},8,[229,353,354],{"class":271},"        if",[229,356,357],{"class":275}," ws.sheet_state ",[229,359,360],{"class":271},"!=",[229,362,363],{"class":239}," \"visible\"",[229,365,366],{"class":275},":\n",[229,368,370,373,376,379,382,385,389,392,395,398,400,403,405,408],{"class":231,"line":369},9,[229,371,372],{"class":275},"            found.append((",[229,374,375],{"class":239},"\"sheet\"",[229,377,378],{"class":275},", ws.title, ",[229,380,381],{"class":271},"f",[229,383,384],{"class":239},"\"",[229,386,388],{"class":387},"sSjpA","{",[229,390,391],{"class":275},"ws.sheet_state",[229,393,394],{"class":387},"}",[229,396,397],{"class":239},", ",[229,399,388],{"class":387},[229,401,402],{"class":275},"ws.max_row",[229,404,394],{"class":387},[229,406,407],{"class":239}," rows\"",[229,409,410],{"class":275},"))\n",[229,412,414,417,420,422],{"class":231,"line":413},10,[229,415,416],{"class":271},"        for",[229,418,419],{"class":275}," letter, dim ",[229,421,345],{"class":271},[229,423,424],{"class":275}," ws.column_dimensions.items():\n",[229,426,428,431,434,437,441,444,447,450,453,456,459,461],{"class":231,"line":427},11,[229,429,430],{"class":271},"            if",[229,432,433],{"class":275}," dim.hidden ",[229,435,436],{"class":271},"and",[229,438,440],{"class":439},"sP0c6"," any",[229,442,443],{"class":275},"(c.value ",[229,445,446],{"class":271},"is",[229,448,449],{"class":271}," not",[229,451,452],{"class":439}," None",[229,454,455],{"class":271}," for",[229,457,458],{"class":275}," c ",[229,460,345],{"class":271},[229,462,463],{"class":275}," ws[letter]):\n",[229,465,467,470,473,475,477,479,481,484,486,489,491,494,496,498,500,503],{"class":231,"line":466},12,[229,468,469],{"class":275},"                found.append((",[229,471,472],{"class":239},"\"hidden column\"",[229,474,397],{"class":275},[229,476,381],{"class":271},[229,478,384],{"class":239},[229,480,388],{"class":387},[229,482,483],{"class":275},"ws.title",[229,485,394],{"class":387},[229,487,488],{"class":239},"!",[229,490,388],{"class":387},[229,492,493],{"class":275},"letter",[229,495,394],{"class":387},[229,497,384],{"class":239},[229,499,397],{"class":275},[229,501,502],{"class":239},"\"contains data\"",[229,504,410],{"class":275},[229,506,508,510,513,515],{"class":231,"line":507},13,[229,509,416],{"class":271},[229,511,512],{"class":275}," idx, dim ",[229,514,345],{"class":271},[229,516,517],{"class":275}," ws.row_dimensions.items():\n",[229,519,521,523,525,527,529,531,533,535,537,539,541,543],{"class":231,"line":520},14,[229,522,430],{"class":271},[229,524,433],{"class":275},[229,526,436],{"class":271},[229,528,440],{"class":439},[229,530,443],{"class":275},[229,532,446],{"class":271},[229,534,449],{"class":271},[229,536,452],{"class":439},[229,538,455],{"class":271},[229,540,458],{"class":275},[229,542,345],{"class":271},[229,544,545],{"class":275}," ws[idx]):\n",[229,547,549,551,554,556,558,560,562,564,566,568,570,573,575,577,579,581],{"class":231,"line":548},15,[229,550,469],{"class":275},[229,552,553],{"class":239},"\"hidden row\"",[229,555,397],{"class":275},[229,557,381],{"class":271},[229,559,384],{"class":239},[229,561,388],{"class":387},[229,563,483],{"class":275},[229,565,394],{"class":387},[229,567,488],{"class":239},[229,569,388],{"class":387},[229,571,572],{"class":275},"idx",[229,574,394],{"class":387},[229,576,384],{"class":239},[229,578,397],{"class":275},[229,580,502],{"class":239},[229,582,410],{"class":275},[229,584,586,588,591,593],{"class":231,"line":585},16,[229,587,416],{"class":271},[229,589,590],{"class":275}," row ",[229,592,345],{"class":271},[229,594,595],{"class":275}," ws.iter_rows():\n",[229,597,599,602,604,606],{"class":231,"line":598},17,[229,600,601],{"class":271},"            for",[229,603,458],{"class":275},[229,605,345],{"class":271},[229,607,608],{"class":275}," row:\n",[229,610,612,615],{"class":231,"line":611},18,[229,613,614],{"class":271},"                if",[229,616,617],{"class":275}," c.comment:\n",[229,619,621,624,627,629,631,633,635,637,639,641,643,646,648,650,652,654,657,659,662,664,666],{"class":231,"line":620},19,[229,622,623],{"class":275},"                    found.append((",[229,625,626],{"class":239},"\"comment\"",[229,628,397],{"class":275},[229,630,381],{"class":271},[229,632,384],{"class":239},[229,634,388],{"class":387},[229,636,483],{"class":275},[229,638,394],{"class":387},[229,640,488],{"class":239},[229,642,388],{"class":387},[229,644,645],{"class":275},"c.coordinate",[229,647,394],{"class":387},[229,649,384],{"class":239},[229,651,397],{"class":275},[229,653,381],{"class":271},[229,655,656],{"class":239},"\"by ",[229,658,388],{"class":387},[229,660,661],{"class":275},"c.comment.author",[229,663,394],{"class":387},[229,665,384],{"class":239},[229,667,410],{"class":275},[229,669,671,673,676,679,682,685,688,690,692,694],{"class":231,"line":670},20,[229,672,614],{"class":271},[229,674,675],{"class":275}," c.number_format ",[229,677,678],{"class":271},"==",[229,680,681],{"class":239}," \";;;\"",[229,683,684],{"class":271}," and",[229,686,687],{"class":275}," c.value ",[229,689,446],{"class":271},[229,691,449],{"class":271},[229,693,452],{"class":439},[229,695,366],{"class":275},[229,697,699,701,704,706,708,710,712,714,716,718,720,722,724,726,728,731],{"class":231,"line":698},21,[229,700,623],{"class":275},[229,702,703],{"class":239},"\"concealed value\"",[229,705,397],{"class":275},[229,707,381],{"class":271},[229,709,384],{"class":239},[229,711,388],{"class":387},[229,713,483],{"class":275},[229,715,394],{"class":387},[229,717,488],{"class":239},[229,719,388],{"class":387},[229,721,645],{"class":275},[229,723,394],{"class":387},[229,725,384],{"class":239},[229,727,397],{"class":275},[229,729,730],{"class":239},"\"format ;;;\"",[229,732,410],{"class":275},[229,734,736,738,741,744,747,750,752,755,758,760,762,765,768],{"class":231,"line":735},22,[229,737,614],{"class":271},[229,739,740],{"class":439}," isinstance",[229,742,743],{"class":275},"(c.value, ",[229,745,746],{"class":439},"str",[229,748,749],{"class":275},") ",[229,751,436],{"class":271},[229,753,754],{"class":275}," c.value.startswith(",[229,756,757],{"class":239},"\"=\"",[229,759,749],{"class":275},[229,761,436],{"class":271},[229,763,764],{"class":239}," \"!\"",[229,766,767],{"class":271}," in",[229,769,770],{"class":275}," c.value:\n",[229,772,774,776,779,781,783,785,787,789,791,793,795,797,799,801],{"class":231,"line":773},23,[229,775,623],{"class":275},[229,777,778],{"class":239},"\"cross-sheet formula\"",[229,780,397],{"class":275},[229,782,381],{"class":271},[229,784,384],{"class":239},[229,786,388],{"class":387},[229,788,483],{"class":275},[229,790,394],{"class":387},[229,792,488],{"class":239},[229,794,388],{"class":387},[229,796,645],{"class":275},[229,798,394],{"class":387},[229,800,384],{"class":239},[229,802,803],{"class":275},", c.value))\n",[229,805,807,809,812,814],{"class":231,"line":806},24,[229,808,339],{"class":271},[229,810,811],{"class":275}," name, dn ",[229,813,345],{"class":271},[229,815,816],{"class":275}," wb.defined_names.items():\n",[229,818,820,823,826,829,831,833,835,838,841,844,847,850,853,856,858,860],{"class":231,"line":819},25,[229,821,822],{"class":275},"        found.append((",[229,824,825],{"class":239},"\"defined name\"",[229,827,828],{"class":275},", name, ",[229,830,381],{"class":271},[229,832,384],{"class":239},[229,834,388],{"class":387},[229,836,837],{"class":275},"dn.attr_text",[229,839,840],{"class":387},"}{",[229,842,843],{"class":239},"' (hidden)'",[229,845,846],{"class":271}," if",[229,848,849],{"class":275}," dn.hidden ",[229,851,852],{"class":271},"else",[229,854,855],{"class":239}," ''",[229,857,394],{"class":387},[229,859,384],{"class":239},[229,861,410],{"class":275},[229,863,865,868],{"class":231,"line":864},26,[229,866,867],{"class":271},"    if",[229,869,870],{"class":275}," wb._external_links:\n",[229,872,874,876,879,881,883,886,889,892,895],{"class":231,"line":873},27,[229,875,822],{"class":275},[229,877,878],{"class":239},"\"external links\"",[229,880,397],{"class":275},[229,882,746],{"class":439},[229,884,885],{"class":275},"(",[229,887,888],{"class":439},"len",[229,890,891],{"class":275},"(wb._external_links)), ",[229,893,894],{"class":239},"\"links to other files\"",[229,896,410],{"class":275},[229,898,900,902,905,907,910,913,915,918,920,923,925,928,930,933,935,938],{"class":231,"line":899},28,[229,901,339],{"class":271},[229,903,904],{"class":275}," field ",[229,906,345],{"class":271},[229,908,909],{"class":275}," (",[229,911,912],{"class":239},"\"creator\"",[229,914,397],{"class":275},[229,916,917],{"class":239},"\"lastModifiedBy\"",[229,919,397],{"class":275},[229,921,922],{"class":239},"\"title\"",[229,924,397],{"class":275},[229,926,927],{"class":239},"\"subject\"",[229,929,397],{"class":275},[229,931,932],{"class":239},"\"keywords\"",[229,934,397],{"class":275},[229,936,937],{"class":239},"\"description\"",[229,939,940],{"class":275},"):\n",[229,942,944,947,949,952],{"class":231,"line":943},29,[229,945,946],{"class":275},"        value ",[229,948,319],{"class":271},[229,950,951],{"class":439}," getattr",[229,953,954],{"class":275},"(wb.properties, field)\n",[229,956,958,960],{"class":231,"line":957},30,[229,959,354],{"class":271},[229,961,962],{"class":275}," value:\n",[229,964,966,968,971],{"class":231,"line":965},31,[229,967,372],{"class":275},[229,969,970],{"class":239},"\"property\"",[229,972,973],{"class":275},", field, value))\n",[229,975,977,980],{"class":231,"line":976},32,[229,978,979],{"class":271},"    return",[229,981,982],{"class":275}," found\n",[229,984,986],{"class":231,"line":985},33,[229,987,297],{"emptyLinePlaceholder":296},[229,989,991,994,997,999,1002,1005],{"class":231,"line":990},34,[229,992,993],{"class":271},"for",[229,995,996],{"class":275}," kind, where, detail ",[229,998,345],{"class":271},[229,1000,1001],{"class":275}," audit(",[229,1003,1004],{"class":239},"\"q3_results.xlsx\"",[229,1006,940],{"class":275},[229,1008,1010,1013,1015,1017,1019,1021,1024,1027,1029,1032,1035,1038,1040,1042,1045,1047,1049],{"class":231,"line":1009},35,[229,1011,1012],{"class":439},"    print",[229,1014,885],{"class":275},[229,1016,381],{"class":271},[229,1018,384],{"class":239},[229,1020,388],{"class":387},[229,1022,1023],{"class":275},"kind",[229,1025,1026],{"class":271},":20",[229,1028,394],{"class":387},[229,1030,1031],{"class":387}," {",[229,1033,1034],{"class":275},"where",[229,1036,1037],{"class":271},":14",[229,1039,394],{"class":387},[229,1041,1031],{"class":387},[229,1043,1044],{"class":275},"detail",[229,1046,394],{"class":387},[229,1048,384],{"class":239},[229,1050,1051],{"class":275},")\n",[10,1053,1054,1055,1058],{},"The audit finds both hidden sheets — including the very hidden Salaries sheet, which Excel's Unhide dialog would not even list — the cost price column, the draft note, the concealed internal code, the comment, the two formulas that pull the margin rate from the hidden Workings sheet, the hidden name pointing at it, and the author and title properties. A formula such as ",[226,1056,1057],{},"=B2*Workings!B1"," is itself a disclosure: it tells the reader that a Workings sheet exists and where the rate lives.",[25,1060,34,1066,34,1069,34,1072,34,1077,34,1083,34,1092,34,1096,34,1102,34,1106,34,1110,34,1114,34,1118,34,1122,34,1127,34,1129,34,1133,34,1135,34,1138,34,1140,34,1143,34,1146,34,1150,34,1152,34,1156,34,1158,34,1161,34,1163,34,1166,34,1169,34,1173,34,1175,34,1177,34,1180,34,1184,34,1186,34,1189,34,1192,34,1195,34,1197,34,1200,34,1202,34,1205,34,1207,34,1210,34,1213,34,1217,34,1219,34,1222,34,1224,34,1227,34,1229,34,1232,34,1235,34,1239,34,1241,34,1244,34,1246,34,1249,34,1251,34,1254,34,1257,34,1261,34,1263,34,1266,34,1268,34,1271,34,1273,34,1276,34,1279,34,1283,34,1285,34,1288,34,1290,34,1293,34,1295],{"viewBox":1061,"role":28,"ariaLabelledBy":1062,"xmlns":32,"style":1065},"154 0 452 312",[1063,1064],"hid-audit-t","hid-audit-d","width:100%;max-width:452px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[36,1067,1068],{"id":1063},"What the audit found in q3_results.xlsx",[40,1070,1071],{"id":1064},"The audit findings as a table. Two hidden sheets, Workings hidden and Salaries very hidden. A hidden column D on Summary with cost prices. A hidden row 6 with a draft note. A concealed value in E2. A comment on B2 by Ana Silva. Cross-sheet formulas in C2 and C3. A hidden defined name MarginRate. The creator, last modified by and title properties.",[44,1073],{"x":1074,"y":47,"width":1075,"height":1076,"fill":50},"154","452","312",[73,1078,1082],{"x":1079,"y":1080,"style":1081},"380.0","31.0","font-size:14px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Audit of q3_results.xlsx",[44,1084],{"x":1085,"y":1086,"width":1087,"height":1088,"rx":47,"fill":1089,"stroke":1090,"style":1091},"170.1","48.0","32.0","24.0","#e7ebef","var(--line,#cdd5e6)","stroke-width:1px",[44,1093],{"x":1094,"y":1086,"width":1095,"height":1088,"rx":47,"fill":1089,"stroke":1090,"style":1091},"202.1","149.7",[73,1097,1101],{"x":1098,"y":1099,"style":1100},"277.0","65.0","font-size:11px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[44,1103],{"x":1104,"y":1086,"width":1105,"height":1088,"rx":47,"fill":1089,"stroke":1090,"style":1091},"351.8","104.7",[73,1107,1109],{"x":1108,"y":1099,"style":1100},"404.2","B",[44,1111],{"x":1112,"y":1086,"width":1113,"height":1088,"rx":47,"fill":1089,"stroke":1090,"style":1091},"456.5","133.4",[73,1115,1117],{"x":1116,"y":1099,"style":1100},"523.2","C",[44,1119],{"x":1085,"y":1120,"width":1087,"height":1121,"rx":47,"fill":1089,"stroke":1090,"style":1091},"72.0","28.0",[73,1123,1126],{"x":1124,"y":1125,"style":1100},"186.1","91.0","1",[44,1128],{"x":1094,"y":1120,"width":1095,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1130,1132],{"x":1098,"y":1125,"style":1131},"font-size:12px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Finding",[44,1134],{"x":1104,"y":1120,"width":1105,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1136,1137],{"x":1108,"y":1125,"style":1131},"Where",[44,1139],{"x":1112,"y":1120,"width":1113,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1141,1142],{"x":1116,"y":1125,"style":1131},"Detail",[44,1144],{"x":1085,"y":1145,"width":1087,"height":1121,"rx":47,"fill":1089,"stroke":1090,"style":1091},"100.0",[73,1147,1149],{"x":1124,"y":1148,"style":1100},"119.0","2",[44,1151],{"x":1094,"y":1145,"width":1095,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1153,1155],{"x":1098,"y":1148,"style":1154},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","sheet",[44,1157],{"x":1104,"y":1145,"width":1105,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1159,1160],{"x":1108,"y":1148,"style":1154},"Workings",[44,1162],{"x":1112,"y":1145,"width":1113,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1164,1165],{"x":1116,"y":1148,"style":1154},"hidden",[44,1167],{"x":1085,"y":1168,"width":1087,"height":1121,"rx":47,"fill":1089,"stroke":1090,"style":1091},"128.0",[73,1170,1172],{"x":1124,"y":1171,"style":1100},"147.0","3",[44,1174],{"x":1094,"y":1168,"width":1095,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1176,1155],{"x":1098,"y":1171,"style":1154},[44,1178],{"x":1104,"y":1168,"width":1105,"height":1121,"rx":47,"fill":90,"stroke":91,"style":1179},"stroke-width:1.5px",[73,1181,1183],{"x":1108,"y":1171,"style":1182},"font-size:12px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","Salaries",[44,1185],{"x":1112,"y":1168,"width":1113,"height":1121,"rx":47,"fill":90,"stroke":91,"style":1179},[73,1187,1188],{"x":1116,"y":1171,"style":1182},"veryHidden",[44,1190],{"x":1085,"y":1191,"width":1087,"height":1121,"rx":47,"fill":1089,"stroke":1090,"style":1091},"156.0",[73,1193,46],{"x":1124,"y":1194,"style":1100},"175.0",[44,1196],{"x":1094,"y":1191,"width":1095,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1198,1199],{"x":1098,"y":1194,"style":1154},"hidden column",[44,1201],{"x":1104,"y":1191,"width":1105,"height":1121,"rx":47,"fill":90,"stroke":91,"style":1179},[73,1203,1204],{"x":1108,"y":1194,"style":1182},"Summary!D",[44,1206],{"x":1112,"y":1191,"width":1113,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1208,1209],{"x":1116,"y":1194,"style":1154},"cost prices",[44,1211],{"x":1085,"y":1212,"width":1087,"height":1121,"rx":47,"fill":1089,"stroke":1090,"style":1091},"184.0",[73,1214,1216],{"x":1124,"y":1215,"style":1100},"203.0","5",[44,1218],{"x":1094,"y":1212,"width":1095,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1220,1221],{"x":1098,"y":1215,"style":1154},"hidden row",[44,1223],{"x":1104,"y":1212,"width":1105,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1225,1226],{"x":1108,"y":1215,"style":1154},"Summary!6",[44,1228],{"x":1112,"y":1212,"width":1113,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1230,1231],{"x":1116,"y":1215,"style":1154},"draft note",[44,1233],{"x":1085,"y":1234,"width":1087,"height":1121,"rx":47,"fill":1089,"stroke":1090,"style":1091},"212.0",[73,1236,1238],{"x":1124,"y":1237,"style":1100},"231.0","6",[44,1240],{"x":1094,"y":1234,"width":1095,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1242,1243],{"x":1098,"y":1237,"style":1154},"concealed value",[44,1245],{"x":1104,"y":1234,"width":1105,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1247,1248],{"x":1108,"y":1237,"style":1154},"Summary!E2",[44,1250],{"x":1112,"y":1234,"width":1113,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1252,1253],{"x":1116,"y":1237,"style":1154},"format ;;;",[44,1255],{"x":1085,"y":1256,"width":1087,"height":1121,"rx":47,"fill":1089,"stroke":1090,"style":1091},"240.0",[73,1258,1260],{"x":1124,"y":1259,"style":1100},"259.0","7",[44,1262],{"x":1094,"y":1256,"width":1095,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1264,1265],{"x":1098,"y":1259,"style":1154},"comment",[44,1267],{"x":1104,"y":1256,"width":1105,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1269,1270],{"x":1108,"y":1259,"style":1154},"Summary!B2",[44,1272],{"x":1112,"y":1256,"width":1113,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1274,1275],{"x":1116,"y":1259,"style":1154},"by Ana Silva",[44,1277],{"x":1085,"y":1278,"width":1087,"height":1121,"rx":47,"fill":1089,"stroke":1090,"style":1091},"268.0",[73,1280,1282],{"x":1124,"y":1281,"style":1100},"287.0","8",[44,1284],{"x":1094,"y":1278,"width":1095,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1286,1287],{"x":1098,"y":1281,"style":1154},"cross-sheet formula",[44,1289],{"x":1104,"y":1278,"width":1105,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1291,1292],{"x":1108,"y":1281,"style":1154},"Summary!C2",[44,1294],{"x":1112,"y":1278,"width":1113,"height":1121,"rx":47,"fill":50,"stroke":1090,"style":1091},[73,1296,1057],{"x":1116,"y":1281,"style":1154},[214,1298,1300],{"id":1299},"step-2-build-a-clean-copy-with-values-only","Step 2 — Build a clean copy with values only",[10,1302,1303,1304,1307],{},"Removing each finding from the original is error-prone, because it is easy to miss one. Build the shared copy by subtraction from a values-only load instead. ",[226,1305,1306],{},"data_only=True"," replaces every formula with the value last calculated, so nothing in the copy can refer to the sheets about to be deleted:",[219,1309,1311],{"className":262,"code":1310,"language":264,"meta":224,"style":224},"from openpyxl.workbook.properties import CalcProperties\n\ndef clean_copy(src, dst, keep_sheets):\n    wb = load_workbook(src, data_only=True)\n    for ws in list(wb.worksheets):\n        if ws.title not in keep_sheets or ws.sheet_state != \"visible\":\n            wb.remove(ws)\n    for ws in wb.worksheets:\n        for idx in sorted((i for i, d in ws.row_dimensions.items() if d.hidden), reverse=True):\n            ws.delete_rows(idx)\n        for letter in sorted((l for l, d in ws.column_dimensions.items() if d.hidden), reverse=True):\n            ws.delete_cols(ws[f\"{letter}1\"].column)\n        for dim in list(ws.column_dimensions.values()) + list(ws.row_dimensions.values()):\n            dim.hidden = False\n        for row in ws.iter_rows():\n            for c in row:\n                c.comment = None\n                if c.number_format == \";;;\":\n                    c.value = None\n                    c.number_format = \"General\"\n    for name in list(wb.defined_names):\n        del wb.defined_names[name]\n    wb._external_links = []\n    wb.properties.creator = \"Finance\"\n    wb.properties.lastModifiedBy = \"Finance\"\n    wb.properties.title = \"Q3 results\"\n    wb.properties.subject = wb.properties.keywords = wb.properties.description = None\n    wb.save(dst)\n\nclean_copy(\"q3_results.xlsx\", \"q3_results_shared.xlsx\", keep_sheets={\"Summary\"})\nshared = load_workbook(\"q3_results_shared.xlsx\")\nprint(shared.sheetnames)\nfor row in shared[\"Summary\"].iter_rows(values_only=True):\n    print(row)\n",[226,1312,1313,1325,1329,1339,1359,1373,1399,1404,1414,1454,1459,1495,1516,1538,1548,1558,1568,1578,1590,1599,1609,1623,1631,1640,1650,1659,1669,1688,1693,1697,1724,1738,1746,1771],{"__ignoreMap":224},[229,1314,1315,1317,1320,1322],{"class":231,"line":232},[229,1316,282],{"class":271},[229,1318,1319],{"class":275}," openpyxl.workbook.properties ",[229,1321,272],{"class":271},[229,1323,1324],{"class":275}," CalcProperties\n",[229,1326,1327],{"class":231,"line":279},[229,1328,297],{"emptyLinePlaceholder":296},[229,1330,1331,1333,1336],{"class":231,"line":293},[229,1332,303],{"class":271},[229,1334,1335],{"class":306}," clean_copy",[229,1337,1338],{"class":275},"(src, dst, keep_sheets):\n",[229,1340,1341,1343,1345,1348,1352,1354,1357],{"class":231,"line":300},[229,1342,316],{"class":275},[229,1344,319],{"class":271},[229,1346,1347],{"class":275}," load_workbook(src, ",[229,1349,1351],{"class":1350},"sa561","data_only",[229,1353,319],{"class":271},[229,1355,1356],{"class":439},"True",[229,1358,1051],{"class":275},[229,1360,1361,1363,1365,1367,1370],{"class":231,"line":313},[229,1362,339],{"class":271},[229,1364,342],{"class":275},[229,1366,345],{"class":271},[229,1368,1369],{"class":439}," list",[229,1371,1372],{"class":275},"(wb.worksheets):\n",[229,1374,1375,1377,1380,1383,1385,1388,1391,1393,1395,1397],{"class":231,"line":325},[229,1376,354],{"class":271},[229,1378,1379],{"class":275}," ws.title ",[229,1381,1382],{"class":271},"not",[229,1384,767],{"class":271},[229,1386,1387],{"class":275}," keep_sheets ",[229,1389,1390],{"class":271},"or",[229,1392,357],{"class":275},[229,1394,360],{"class":271},[229,1396,363],{"class":239},[229,1398,366],{"class":275},[229,1400,1401],{"class":231,"line":336},[229,1402,1403],{"class":275},"            wb.remove(ws)\n",[229,1405,1406,1408,1410,1412],{"class":231,"line":351},[229,1407,339],{"class":271},[229,1409,342],{"class":275},[229,1411,345],{"class":271},[229,1413,348],{"class":275},[229,1415,1416,1418,1421,1423,1426,1429,1431,1434,1436,1439,1442,1445,1448,1450,1452],{"class":231,"line":369},[229,1417,416],{"class":271},[229,1419,1420],{"class":275}," idx ",[229,1422,345],{"class":271},[229,1424,1425],{"class":439}," sorted",[229,1427,1428],{"class":275},"((i ",[229,1430,993],{"class":271},[229,1432,1433],{"class":275}," i, d ",[229,1435,345],{"class":271},[229,1437,1438],{"class":275}," ws.row_dimensions.items() ",[229,1440,1441],{"class":271},"if",[229,1443,1444],{"class":275}," d.hidden), ",[229,1446,1447],{"class":1350},"reverse",[229,1449,319],{"class":271},[229,1451,1356],{"class":439},[229,1453,940],{"class":275},[229,1455,1456],{"class":231,"line":413},[229,1457,1458],{"class":275},"            ws.delete_rows(idx)\n",[229,1460,1461,1463,1466,1468,1470,1473,1475,1478,1480,1483,1485,1487,1489,1491,1493],{"class":231,"line":427},[229,1462,416],{"class":271},[229,1464,1465],{"class":275}," letter ",[229,1467,345],{"class":271},[229,1469,1425],{"class":439},[229,1471,1472],{"class":275},"((l ",[229,1474,993],{"class":271},[229,1476,1477],{"class":275}," l, d ",[229,1479,345],{"class":271},[229,1481,1482],{"class":275}," ws.column_dimensions.items() ",[229,1484,1441],{"class":271},[229,1486,1444],{"class":275},[229,1488,1447],{"class":1350},[229,1490,319],{"class":271},[229,1492,1356],{"class":439},[229,1494,940],{"class":275},[229,1496,1497,1500,1502,1504,1506,1508,1510,1513],{"class":231,"line":466},[229,1498,1499],{"class":275},"            ws.delete_cols(ws[",[229,1501,381],{"class":271},[229,1503,384],{"class":239},[229,1505,388],{"class":387},[229,1507,493],{"class":275},[229,1509,394],{"class":387},[229,1511,1512],{"class":239},"1\"",[229,1514,1515],{"class":275},"].column)\n",[229,1517,1518,1520,1523,1525,1527,1530,1533,1535],{"class":231,"line":507},[229,1519,416],{"class":271},[229,1521,1522],{"class":275}," dim ",[229,1524,345],{"class":271},[229,1526,1369],{"class":439},[229,1528,1529],{"class":275},"(ws.column_dimensions.values()) ",[229,1531,1532],{"class":271},"+",[229,1534,1369],{"class":439},[229,1536,1537],{"class":275},"(ws.row_dimensions.values()):\n",[229,1539,1540,1543,1545],{"class":231,"line":520},[229,1541,1542],{"class":275},"            dim.hidden ",[229,1544,319],{"class":271},[229,1546,1547],{"class":439}," False\n",[229,1549,1550,1552,1554,1556],{"class":231,"line":548},[229,1551,416],{"class":271},[229,1553,590],{"class":275},[229,1555,345],{"class":271},[229,1557,595],{"class":275},[229,1559,1560,1562,1564,1566],{"class":231,"line":585},[229,1561,601],{"class":271},[229,1563,458],{"class":275},[229,1565,345],{"class":271},[229,1567,608],{"class":275},[229,1569,1570,1573,1575],{"class":231,"line":598},[229,1571,1572],{"class":275},"                c.comment ",[229,1574,319],{"class":271},[229,1576,1577],{"class":439}," None\n",[229,1579,1580,1582,1584,1586,1588],{"class":231,"line":611},[229,1581,614],{"class":271},[229,1583,675],{"class":275},[229,1585,678],{"class":271},[229,1587,681],{"class":239},[229,1589,366],{"class":275},[229,1591,1592,1595,1597],{"class":231,"line":620},[229,1593,1594],{"class":275},"                    c.value ",[229,1596,319],{"class":271},[229,1598,1577],{"class":439},[229,1600,1601,1604,1606],{"class":231,"line":670},[229,1602,1603],{"class":275},"                    c.number_format ",[229,1605,319],{"class":271},[229,1607,1608],{"class":239}," \"General\"\n",[229,1610,1611,1613,1616,1618,1620],{"class":231,"line":698},[229,1612,339],{"class":271},[229,1614,1615],{"class":275}," name ",[229,1617,345],{"class":271},[229,1619,1369],{"class":439},[229,1621,1622],{"class":275},"(wb.defined_names):\n",[229,1624,1625,1628],{"class":231,"line":735},[229,1626,1627],{"class":271},"        del",[229,1629,1630],{"class":275}," wb.defined_names[name]\n",[229,1632,1633,1636,1638],{"class":231,"line":773},[229,1634,1635],{"class":275},"    wb._external_links ",[229,1637,319],{"class":271},[229,1639,333],{"class":275},[229,1641,1642,1645,1647],{"class":231,"line":806},[229,1643,1644],{"class":275},"    wb.properties.creator ",[229,1646,319],{"class":271},[229,1648,1649],{"class":239}," \"Finance\"\n",[229,1651,1652,1655,1657],{"class":231,"line":819},[229,1653,1654],{"class":275},"    wb.properties.lastModifiedBy ",[229,1656,319],{"class":271},[229,1658,1649],{"class":239},[229,1660,1661,1664,1666],{"class":231,"line":864},[229,1662,1663],{"class":275},"    wb.properties.title ",[229,1665,319],{"class":271},[229,1667,1668],{"class":239}," \"Q3 results\"\n",[229,1670,1671,1674,1676,1679,1681,1684,1686],{"class":231,"line":873},[229,1672,1673],{"class":275},"    wb.properties.subject ",[229,1675,319],{"class":271},[229,1677,1678],{"class":275}," wb.properties.keywords ",[229,1680,319],{"class":271},[229,1682,1683],{"class":275}," wb.properties.description ",[229,1685,319],{"class":271},[229,1687,1577],{"class":439},[229,1689,1690],{"class":231,"line":899},[229,1691,1692],{"class":275},"    wb.save(dst)\n",[229,1694,1695],{"class":231,"line":943},[229,1696,297],{"emptyLinePlaceholder":296},[229,1698,1699,1702,1704,1706,1709,1711,1714,1716,1718,1721],{"class":231,"line":957},[229,1700,1701],{"class":275},"clean_copy(",[229,1703,1004],{"class":239},[229,1705,397],{"class":275},[229,1707,1708],{"class":239},"\"q3_results_shared.xlsx\"",[229,1710,397],{"class":275},[229,1712,1713],{"class":1350},"keep_sheets",[229,1715,319],{"class":271},[229,1717,388],{"class":275},[229,1719,1720],{"class":239},"\"Summary\"",[229,1722,1723],{"class":275},"})\n",[229,1725,1726,1729,1731,1734,1736],{"class":231,"line":965},[229,1727,1728],{"class":275},"shared ",[229,1730,319],{"class":271},[229,1732,1733],{"class":275}," load_workbook(",[229,1735,1708],{"class":239},[229,1737,1051],{"class":275},[229,1739,1740,1743],{"class":231,"line":976},[229,1741,1742],{"class":439},"print",[229,1744,1745],{"class":275},"(shared.sheetnames)\n",[229,1747,1748,1750,1752,1754,1757,1759,1762,1765,1767,1769],{"class":231,"line":985},[229,1749,993],{"class":271},[229,1751,590],{"class":275},[229,1753,345],{"class":271},[229,1755,1756],{"class":275}," shared[",[229,1758,1720],{"class":239},[229,1760,1761],{"class":275},"].iter_rows(",[229,1763,1764],{"class":1350},"values_only",[229,1766,319],{"class":271},[229,1768,1356],{"class":439},[229,1770,940],{"class":275},[229,1772,1773,1775],{"class":231,"line":990},[229,1774,1012],{"class":439},[229,1776,1777],{"class":275},"(row)\n",[10,1779,1780,1781,1784,1785,1788,1789,1792,1793,1795],{},"The copy has one sheet with the region, revenue and margin — the margin now a number, 8,676 for North, rather than a formula. Hidden rows and columns are deleted rather than unhidden, working from the bottom and the right so the positions of those still to delete do not shift. The concealed value is cleared, not just made visible; its \"Internal code\" heading stays, so delete that column as well if even the heading should not be seen. One detail is easy to miss: ",[226,1782,1783],{},"delete_rows"," and ",[226,1786,1787],{},"delete_cols"," shift the cells but not the row and column ",[14,1790,1791],{},"settings",", so the hidden flag stays on column D and would now hide whatever moved into it — the audit in the next step catches exactly that if the flags are not cleared, which is why the function resets every hidden flag after deleting. Deleting a column with openpyxl also does not adjust formulas elsewhere, which is one more reason to work from values: after ",[226,1794,1306],{}," there are no formulas left to break.",[214,1797,1799],{"id":1798},"step-3-audit-the-copy-before-it-goes-out","Step 3 — Audit the copy before it goes out",[10,1801,1802],{},"Run the same audit on the file you are about to send. The only acceptable findings are ones you chose to keep:",[219,1804,1806],{"className":262,"code":1805,"language":264,"meta":224,"style":224},"remaining = audit(\"q3_results_shared.xlsx\")\nfor kind, where, detail in remaining:\n    print(f\"{kind:20} {where:14} {detail}\")\nunexpected = [f for f in remaining if f[0] != \"property\"]\nassert not unexpected, f\"still contains: {unexpected}\"\nprint(\"clean — only the properties set deliberately remain\")\n",[226,1807,1808,1821,1832,1868,1906,1931],{"__ignoreMap":224},[229,1809,1810,1813,1815,1817,1819],{"class":231,"line":232},[229,1811,1812],{"class":275},"remaining ",[229,1814,319],{"class":271},[229,1816,1001],{"class":275},[229,1818,1708],{"class":239},[229,1820,1051],{"class":275},[229,1822,1823,1825,1827,1829],{"class":231,"line":279},[229,1824,993],{"class":271},[229,1826,996],{"class":275},[229,1828,345],{"class":271},[229,1830,1831],{"class":275}," remaining:\n",[229,1833,1834,1836,1838,1840,1842,1844,1846,1848,1850,1852,1854,1856,1858,1860,1862,1864,1866],{"class":231,"line":293},[229,1835,1012],{"class":439},[229,1837,885],{"class":275},[229,1839,381],{"class":271},[229,1841,384],{"class":239},[229,1843,388],{"class":387},[229,1845,1023],{"class":275},[229,1847,1026],{"class":271},[229,1849,394],{"class":387},[229,1851,1031],{"class":387},[229,1853,1034],{"class":275},[229,1855,1037],{"class":271},[229,1857,394],{"class":387},[229,1859,1031],{"class":387},[229,1861,1044],{"class":275},[229,1863,394],{"class":387},[229,1865,384],{"class":239},[229,1867,1051],{"class":275},[229,1869,1870,1873,1875,1878,1880,1883,1885,1888,1890,1893,1895,1898,1900,1903],{"class":231,"line":300},[229,1871,1872],{"class":275},"unexpected ",[229,1874,319],{"class":271},[229,1876,1877],{"class":275}," [f ",[229,1879,993],{"class":271},[229,1881,1882],{"class":275}," f ",[229,1884,345],{"class":271},[229,1886,1887],{"class":275}," remaining ",[229,1889,1441],{"class":271},[229,1891,1892],{"class":275}," f[",[229,1894,47],{"class":439},[229,1896,1897],{"class":275},"] ",[229,1899,360],{"class":271},[229,1901,1902],{"class":239}," \"property\"",[229,1904,1905],{"class":275},"]\n",[229,1907,1908,1911,1913,1916,1918,1921,1923,1926,1928],{"class":231,"line":313},[229,1909,1910],{"class":271},"assert",[229,1912,449],{"class":271},[229,1914,1915],{"class":275}," unexpected, ",[229,1917,381],{"class":271},[229,1919,1920],{"class":239},"\"still contains: ",[229,1922,388],{"class":387},[229,1924,1925],{"class":275},"unexpected",[229,1927,394],{"class":387},[229,1929,1930],{"class":239},"\"\n",[229,1932,1933,1935,1937,1940],{"class":231,"line":325},[229,1934,1742],{"class":439},[229,1936,885],{"class":275},[229,1938,1939],{"class":239},"\"clean — only the properties set deliberately remain\"",[229,1941,1051],{"class":275},[10,1943,1944],{},"Only the neutral properties set in Step 2 remain. Make this check part of the job that produces the shared file, so a new hidden sheet or comment added to the source next quarter stops the send instead of going out.",[25,1946,34,1951,34,1954,34,1957,34,1960,34,1964,34,1971,34,1977,34,1981,34,1987,34,1994,34,1998,34,2003,34,2007,34,2012,34,2017,34,2024,34,2029,34,2033,34,2037,34,2042,34,2045,34,2050,34,2053],{"viewBox":1947,"role":28,"ariaLabelledBy":1948,"xmlns":32,"style":33},"4 0 752 207",[1949,1950],"hid-approach-t","hid-approach-d",[36,1952,1953],{"id":1949},"Hiding data versus removing it",[40,1955,1956],{"id":1950},"Two panels. Hiding sheets, rows and columns or protecting them leaves the data in the file, where anyone can reveal it with a right-click, a script or by unzipping the file. Building a values-only copy that contains only the shared sheet removes the data from the file entirely, and a second audit confirms nothing hidden remains.",[44,1958],{"x":46,"y":47,"width":48,"height":1959,"fill":50},"207",[44,1961],{"x":53,"y":87,"width":1962,"height":1194,"rx":1963,"fill":90,"stroke":91,"style":60},"351.0","14",[62,1965,1967],{"transform":1966},"translate(182.5,29.0) scale(1.083)",[66,1968],{"d":1969,"fill":69,"stroke":98,"style":1970},"M12 3.5l9.5 17h-19z M12 10v5 M12 17.8v.4","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[73,1972,1976],{"x":1973,"y":1974,"style":1975},"195.5","78.0","font-size:14px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:middle","Hide or protect",[231,1978],{"x1":1979,"y1":1125,"x2":1980,"y2":1125,"stroke":91,"style":1091},"36.0","355.0",[73,1982,1986],{"x":1983,"y":1984,"style":1985},"60.0","111.0","font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:start","data still in the file",[62,1988,1990],{"transform":1989},"translate(38.5,99.5) scale(0.625)",[66,1991],{"d":1992,"fill":69,"stroke":91,"style":1993},"M6 6l12 12 M18 6L6 18","stroke-width:2.88px;stroke-linecap:round;stroke-linejoin:round",[73,1995,1997],{"x":1983,"y":1996,"style":1985},"137.0","unhide or unzip reveals it",[62,1999,2001],{"transform":2000},"translate(38.5,125.5) scale(0.625)",[66,2002],{"d":1992,"fill":69,"stroke":91,"style":1993},[73,2004,2006],{"x":1983,"y":2005,"style":1985},"163.0","formulas point at it",[62,2008,2010],{"transform":2009},"translate(38.5,151.5) scale(0.625)",[66,2011],{"d":1992,"fill":69,"stroke":91,"style":1993},[44,2013],{"x":2014,"y":87,"width":1962,"height":1194,"rx":1963,"fill":2015,"stroke":2016,"style":60},"389.0","#d9f4f1","var(--teal,#0f9488)",[62,2018,2020],{"transform":2019},"translate(551.5,29.0) scale(1.083)",[66,2021],{"d":2022,"fill":69,"stroke":2023,"style":1970},"M5 12.5l4.5 4.5L19 7","var(--teal-ink,#0b6157)",[73,2025,2028],{"x":2026,"y":1974,"style":2027},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","Values-only clean copy",[231,2030],{"x1":2031,"y1":1125,"x2":2032,"y2":1125,"stroke":2016,"style":1091},"405.0","724.0",[73,2034,2036],{"x":2035,"y":1984,"style":1985},"429.0","hidden data removed",[62,2038,2040],{"transform":2039},"translate(407.5,99.5) scale(0.625)",[66,2041],{"d":2022,"fill":69,"stroke":2016,"style":1993},[73,2043,2044],{"x":2035,"y":1996,"style":1985},"no formulas to follow",[62,2046,2048],{"transform":2047},"translate(407.5,125.5) scale(0.625)",[66,2049],{"d":2022,"fill":69,"stroke":2016,"style":1993},[73,2051,2052],{"x":2035,"y":2005,"style":1985},"audited before sending",[62,2054,2056],{"transform":2055},"translate(407.5,151.5) scale(0.625)",[66,2057],{"d":2022,"fill":69,"stroke":2016,"style":1993},[214,2059,2061],{"id":2060},"what-this-does-not-cover","What this does not cover",[10,2063,2064,2065,2069,2070,2073,2074,2077,2078,2081,2082,2085,2086,2089,2090,2094],{},"openpyxl sees most of a workbook but not all of it. ",[2066,2067,2068],"strong",{},"Pivot tables"," keep a cache of their source data inside the file — a pivot on a summary sheet can carry every row of the hidden data it summarises — so remove pivots from a shared copy or rebuild the summary as plain values. ",[2066,2071,2072],{},"Images"," can contain text or metadata of their own. Macro-enabled files carry ",[2066,2075,2076],{},"VBA code"," that openpyxl discards unless ",[226,2079,2080],{},"keep_vba=True",", and ",[2066,2083,2084],{},"threaded comments"," from newer Excel versions are stored separately from the notes openpyxl reads. For a file going to an external party, run Excel's ",[14,2087,2088],{},"File → Info → Check for Issues → Inspect Document"," on the result as a final check, or share a PDF when the recipient only needs to read it; ",[19,2091,2093],{"href":2092},"\u002Fautomating-reporting-workflows\u002Fexporting-excel-reports-to-pdf\u002F","Exporting Excel Reports to PDF"," covers that route.",[214,2096,2098],{"id":2097},"common-pitfalls","Common pitfalls",[2100,2101,2102,2109,2126,2132,2141,2147],"ul",{},[2103,2104,2105,2108],"li",{},[2066,2106,2107],{},"Treating hidden as private."," Hidden and protected data is still in the file; remove it.",[2103,2110,2111,2114,2115,2118,2119,1784,2122,2125],{},[2066,2112,2113],{},"Missing very hidden sheets."," Check ",[226,2116,2117],{},"sheet_state"," for both ",[226,2120,2121],{},"\"hidden\"",[226,2123,2124],{},"\"veryHidden\"",".",[2103,2127,2128,2131],{},[2066,2129,2130],{},"Leaving formulas in."," A cross-sheet formula reveals structure and breaks when sheets are removed; share values.",[2103,2133,2134,2137,2138,2140],{},[2066,2135,2136],{},"Loading without cached values."," ",[226,2139,1306],{}," needs a file last saved by a spreadsheet application; a file written by openpyxl has no calculated values to keep.",[2103,2142,2143,2146],{},[2066,2144,2145],{},"Forgetting metadata."," Authors, titles and comments carry names; reset them.",[2103,2148,2149,2152],{},[2066,2150,2151],{},"Pivot caches."," They hold source data; remove pivots from shared copies.",[214,2154,2156],{"id":2155},"performance-notes","Performance notes",[10,2158,2159],{},"The audit reads every cell once, which is quick for report-sized workbooks. For very large sheets, skip the cell loop on sheets you will remove anyway, and audit only the sheets you intend to share.",[214,2161,2163],{"id":2162},"conclusion","Conclusion",[10,2165,2166,2167,2169,2170,2172],{},"Audit a workbook before sharing it: hidden and very hidden sheets, hidden rows and columns with content, ",[226,2168,251],{}," formats, comments, cross-sheet formulas, defined names, external links and document properties. Build the shared copy from a ",[226,2171,1306],{}," load, keeping only visible sheets you choose, deleting hidden rows and columns, clearing comments and names and resetting properties. Audit the copy again, and treat pivot caches, images and macros as a final manual check.",[214,2174,2176],{"id":2175},"frequently-asked-questions","Frequently asked questions",[10,2178,2179,2182],{},[2066,2180,2181],{},"How do I find hidden sheets in an Excel file with Python?","\nLoad it with openpyxl and check each worksheet's sheet_state. \"hidden\" sheets can be unhidden from Excel's menu; \"veryHidden\" sheets do not appear in that menu at all and can only be revealed through the VBA editor or code — which makes them easy to forget about.",[10,2184,2185,2188],{},[2066,2186,2187],{},"What hidden data can an Excel file contain?","\nHidden and very hidden sheets, hidden rows and columns, cells formatted with ;;; so their values do not show, comments and notes with author names, defined names, formulas that reveal where numbers come from, links to other files, pivot caches holding source data, and document properties such as the author.",[10,2190,2191,2194],{},[2066,2192,2193],{},"How do I share only the values from an Excel workbook?","\nLoad it with data_only=True so formulas are replaced by their last calculated values, remove the sheets, rows, columns, comments and names you do not want to share, reset the document properties and save a new copy. Then audit that copy again before sending it.",[10,2196,2197,2200],{},[2066,2198,2199],{},"Is protecting or hiding a sheet enough to keep data private?","\nNo. Hidden and protected sheets are still in the file, and anyone with basic tools can read them. Data that the recipient must not see has to be removed from the copy you send, not hidden in it.",[214,2202,2204],{"id":2203},"related","Related",[2100,2206,2207,2213,2220,2227],{},[2103,2208,2209,2210,2212],{},"Up one level: ",[19,2211,22],{"href":21}," — protection and sharing in general.",[2103,2214,2215,2219],{},[19,2216,2218],{"href":2217},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fhide-sheets-rows-and-columns-with-openpyxl\u002F","Hide Sheets, Rows and Columns with openpyxl"," — the hiding this page undoes.",[2103,2221,2222,2226],{},[19,2223,2225],{"href":2224},"\u002Fgetting-started-with-python-excel-automation\u002Fusing-openpyxl-for-excel-file-manipulation\u002Fset-workbook-properties-with-python\u002F","Set Workbook Properties with Python"," — the metadata fields.",[2103,2228,2229,2233],{},[19,2230,2232],{"href":2231},"\u002Fgetting-started-with-python-excel-automation\u002Fworking-with-excel-formulas-in-python\u002Ffind-formula-errors-in-a-workbook-with-python\u002F","Find Formula Errors in a Workbook with Python"," — another audit pass worth running.",[2235,2236,2237],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}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}",{"title":224,"searchDepth":279,"depth":279,"links":2239},[2240,2241,2242,2243,2244,2245,2246,2247,2248,2249],{"id":216,"depth":279,"text":217},{"id":255,"depth":279,"text":256},{"id":1299,"depth":279,"text":1300},{"id":1798,"depth":279,"text":1799},{"id":2060,"depth":279,"text":2061},{"id":2097,"depth":279,"text":2098},{"id":2155,"depth":279,"text":2156},{"id":2162,"depth":279,"text":2163},{"id":2175,"depth":279,"text":2176},{"id":2203,"depth":279,"text":2204},"2026-09-25","A workbook sent outside the team often carries more than the visible numbers: hidden and very hidden sheets, hidden rows and columns, comments with names in them, formulas that point at a salary sheet, named ranges and author details. Audit a workbook for all of it with openpyxl, then build a clean copy with values only, and check the copy before it goes out.","md",[2254,2256,2258,2260],{"q":2181,"a":2255},"Load it with openpyxl and check each worksheet's sheet_state. \"hidden\" sheets can be unhidden from Excel's menu; \"veryHidden\" sheets do not appear in that menu at all and can only be revealed through the VBA editor or code — which makes them easy to forget about.",{"q":2187,"a":2257},"Hidden and very hidden sheets, hidden rows and columns, cells formatted with ;;; so their values do not show, comments and notes with author names, defined names, formulas that reveal where numbers come from, links to other files, pivot caches holding source data, and document properties such as the author.",{"q":2193,"a":2259},"Load it with data_only=True so formulas are replaced by their last calculated values, remove the sheets, rows, columns, comments and names you do not want to share, reset the document properties and save a new copy. Then audit that copy again before sending it.",{"q":2199,"a":2261},"No. Hidden and protected sheets are still in the file, and anyone with basic tools can read them. Data that the recipient must not see has to be removed from the copy you send, not hidden in it.","remove hidden data before sharing an excel file",null,{"breadcrumb":2265},[2266,2269,2272],{"name":2267,"item":2268},"Home","\u002F",{"name":2270,"item":2271},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":22,"item":21},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fremove-hidden-data-before-sharing-an-excel-file",{"title":2275,"description":2276},"Remove Hidden Sheets, Comments and Metadata from Excel (Python)","Clean an Excel workbook before sharing it: find hidden and veryHidden sheets, hidden rows and columns, ;;; formats, comments, defined names, cross-sheet formulas, external links and document properties with openpyxl, then save a values-only copy and re-audit it.","remove-hidden-data-before-sharing-an-excel-file","formatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fremove-hidden-data-before-sharing-an-excel-file\u002Findex",[2280,2281],"protection-and-sharing","openpyxl","how-to","eUNEkk6uZjviQe7oiX-Vi0UXdzzzGfw39MwyTPNjoAM",[2285,2289],{"title":2286,"path":2287,"stem":2288,"children":-1},"Protect Workbook Structure with openpyxl","\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fprotect-workbook-structure-with-openpyxl","formatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fprotect-workbook-structure-with-openpyxl\u002Findex",{"title":2290,"path":2291,"stem":2292,"children":-1},"Remove Sheet Protection from a Workbook You Own with openpyxl","\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fremove-sheet-protection-with-openpyxl","formatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fremove-sheet-protection-with-openpyxl\u002Findex",[2294,2296],{"path":2295,"title":2270},"\u002Fformatting-and-charting-excel-reports-with-python",{"path":2297,"title":22},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks",[],[2300,2303,2306,2309,2312,2315],{"path":2301,"title":2302,"kind":2282},"\u002Fadvanced-data-transformation-and-cleaning\u002Fvalidating-excel-data-with-python\u002Fanonymise-personal-data-in-an-excel-file-with-python","Anonymise Personal Data in an Excel File with Python",{"path":2304,"title":2305,"kind":2282},"\u002Fautomating-reporting-workflows\u002Fexporting-excel-reports-to-pdf\u002Fpassword-protect-a-pdf-exported-from-excel","Password-Protect a PDF Exported from Excel",{"path":2307,"title":2308,"kind":2282},"\u002Fautomating-reporting-workflows\u002Fexporting-excel-reports-to-pdf\u002Fsign-a-pdf-report-digitally-with-python","Sign a PDF Report Digitally with Python",{"path":2310,"title":2311,"kind":2282},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fdefine-names-and-protect-sheets-with-xlsxwriter","Define Names and Protect Sheets with XlsxWriter",{"path":2313,"title":2314,"kind":2282},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fadd-comments-and-notes-to-excel-cells-with-python","Add Comments and Notes to Excel Cells with Python",{"path":2316,"title":2218,"kind":2282},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fprotecting-and-sharing-excel-workbooks\u002Fhide-sheets-rows-and-columns-with-openpyxl",1790972117039]