[{"data":1,"prerenderedAt":2135},["ShallowReactive",2],{"doc:\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-images-inside-cells-with-xlsxwriter":3,"surround:\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-images-inside-cells-with-xlsxwriter":2102,"ancestors:\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-images-inside-cells-with-xlsxwriter":2110,"children:\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-images-inside-cells-with-xlsxwriter":2115,"related:\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-images-inside-cells-with-xlsxwriter":2116},{"id":4,"title":5,"body":6,"dateModified":2069,"datePublished":2069,"description":2070,"extension":2071,"faq":2072,"keyword":2081,"kind":2082,"meta":2083,"navigation":204,"path":2091,"seo":2092,"slug":2095,"stem":2096,"topics":2097,"type":2100,"__hash__":2101},"docs\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-images-inside-cells-with-xlsxwriter\u002Findex.md","Embed Images Inside Cells with xlsxwriter",{"type":7,"value":8,"toc":2055},"minimark",[9,29,127,132,165,175,336,340,350,651,658,662,665,839,851,1033,1037,1048,1308,1318,1322,1332,1434,1441,1445,1448,1476,1552,1658,1662,1682,1846,1853,1857,1958,1962,1965,1969,1983,1987,1993,1999,2005,2011,2015,2051],[10,11,12,13,17,18,22,23,28],"p",{},"A product catalogue with a photo column looks simple until someone sorts it by price. Pictures inserted the\ntraditional way float on a drawing layer above the grid, anchored to a cell but not part of it, so the rows\nmove and the photos stay where they were — every product now wears somebody else's picture. Current versions\nof Excel can instead place a picture ",[14,15,16],"em",{},"in"," a cell, as its value, and xlsxwriter writes that with\n",[19,20,21],"code",{},"embed_image()",". The picture then sorts, filters, copies and resizes with its row like any other value. This\nguide, part of ",[24,25,27],"a",{"href":26},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002F","Inserting Images and Logos into Excel",",\nshows how to use it and when the floating kind is still the right choice.",[30,31,39,40,39,44,39,48,39,55,39,64,39,71,39,78,39,83,39,87,39,91,39,95,39,100,39,105,39,109,39,112,39,115,39,118,39,121],"svg",{"viewBox":32,"role":33,"ariaLabelledBy":34,"xmlns":37,"style":38},"0 0 760 214","img",[35,36],"emb-kinds-t","emb-kinds-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:760px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[41,42,43],"title",{"id":35},"Floating images versus images embedded in cells",[45,46,47],"desc",{"id":36},"A floating image from insert_image sits on the drawing layer, anchored to a cell, and can be positioned and sized freely but does not sort with rows. An embedded image from embed_image is the value of a cell, sorts and filters with its row, and is sized by the cell.",[49,50],"rect",{"x":51,"y":51,"width":52,"height":53,"fill":54},"0","760","214","#ffffff",[49,56],{"x":57,"y":57,"width":58,"height":59,"rx":60,"fill":61,"stroke":62,"style":63},"20","350","150","14","#fdefd8","var(--gold,#b4740a)","stroke-width:2px",[65,66,70],"text",{"x":67,"y":68,"style":69},"195","46","font-size:13px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","insert_image (floating)",[72,73],"line",{"x1":74,"y1":75,"x2":76,"y2":75,"stroke":62,"style":77},"36","56","354","stroke-width:1px",[65,79,82],{"x":67,"y":80,"style":81},"78","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","on the drawing layer",[65,84,86],{"x":67,"y":85,"style":81},"101","free position and scale",[65,88,90],{"x":67,"y":89,"style":81},"124","stays put when rows sort",[65,92,94],{"x":67,"y":93,"style":81},"147","logos, headers, charts",[49,96],{"x":97,"y":57,"width":58,"height":59,"rx":60,"fill":98,"stroke":99,"style":63},"390","#d9f4f1","var(--teal,#0f9488)",[65,101,104],{"x":102,"y":68,"style":103},"565","font-size:13px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","embed_image (in cell)",[72,106],{"x1":107,"y1":75,"x2":108,"y2":75,"stroke":99,"style":77},"406","724",[65,110,111],{"x":102,"y":80,"style":81},"the cell value itself",[65,113,114],{"x":102,"y":85,"style":81},"sized by row and column",[65,116,117],{"x":102,"y":89,"style":81},"sorts and filters with row",[65,119,120],{"x":102,"y":93,"style":81},"catalogues, status icons",[65,122,126],{"x":123,"y":124,"style":125},"380","200","font-size:12.5px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle","if the picture belongs to a row, embed it",[128,129,131],"h2",{"id":130},"prerequisites","Prerequisites",[133,134,139],"pre",{"className":135,"code":136,"language":137,"meta":138,"style":138},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install xlsxwriter pillow pandas openpyxl\n","bash","",[19,140,141],{"__ignoreMap":138},[142,143,145,149,153,156,159,162],"span",{"class":72,"line":144},1,[142,146,148],{"class":147},"sMTad","pip",[142,150,152],{"class":151},"srMev"," install",[142,154,155],{"class":151}," xlsxwriter",[142,157,158],{"class":151}," pillow",[142,160,161],{"class":151}," pandas",[142,163,164],{"class":151}," openpyxl\n",[10,166,167,170,171,174],{},[19,168,169],{},"embed_image"," is available in recent xlsxwriter releases (it is present in the 3.2 series used here). Readers need a version of Excel that\nsupports pictures in cells, such as Excel for Microsoft 365; older versions show ",[19,172,173],{},"#VALUE!"," in those cells, which is covered in Step 5. The\nsnippet below draws two small placeholder product images with Pillow so the examples run without any assets:",[133,176,180],{"className":177,"code":178,"language":179,"meta":138,"style":138},"language-python shiki shiki-themes github-light github-dark-high-contrast","from PIL import Image, ImageDraw\n\nfor name, colour in [(\"widget\", \"#0f9488\"), (\"gadget\", \"#5b5cf0\")]:\n    picture = Image.new(\"RGB\", (240, 240), \"white\")\n    ImageDraw.Draw(picture).ellipse((20, 20, 220, 220), fill=colour)\n    picture.save(f\"{name}.png\")\n","python",[19,181,182,199,206,243,277,309],{"__ignoreMap":138},[142,183,184,188,192,195],{"class":72,"line":144},[142,185,187],{"class":186},"s-kum","from",[142,189,191],{"class":190},"sP0c6"," PIL",[142,193,194],{"class":186}," import",[142,196,198],{"class":197},"skGVy"," Image, ImageDraw\n",[142,200,202],{"class":72,"line":201},2,[142,203,205],{"emptyLinePlaceholder":204},true,"\n",[142,207,209,212,215,217,220,223,226,229,232,235,237,240],{"class":72,"line":208},3,[142,210,211],{"class":186},"for",[142,213,214],{"class":197}," name, colour ",[142,216,16],{"class":186},[142,218,219],{"class":197}," [(",[142,221,222],{"class":151},"\"widget\"",[142,224,225],{"class":197},", ",[142,227,228],{"class":151},"\"#0f9488\"",[142,230,231],{"class":197},"), (",[142,233,234],{"class":151},"\"gadget\"",[142,236,225],{"class":197},[142,238,239],{"class":151},"\"#5b5cf0\"",[142,241,242],{"class":197},")]:\n",[142,244,246,249,252,255,258,261,264,266,268,271,274],{"class":72,"line":245},4,[142,247,248],{"class":197},"    picture ",[142,250,251],{"class":186},"=",[142,253,254],{"class":197}," Image.new(",[142,256,257],{"class":151},"\"RGB\"",[142,259,260],{"class":197},", (",[142,262,263],{"class":190},"240",[142,265,225],{"class":197},[142,267,263],{"class":190},[142,269,270],{"class":197},"), ",[142,272,273],{"class":151},"\"white\"",[142,275,276],{"class":197},")\n",[142,278,280,283,285,287,289,291,294,296,298,300,304,306],{"class":72,"line":279},5,[142,281,282],{"class":197},"    ImageDraw.Draw(picture).ellipse((",[142,284,57],{"class":190},[142,286,225],{"class":197},[142,288,57],{"class":190},[142,290,225],{"class":197},[142,292,293],{"class":190},"220",[142,295,225],{"class":197},[142,297,293],{"class":190},[142,299,270],{"class":197},[142,301,303],{"class":302},"sa561","fill",[142,305,251],{"class":186},[142,307,308],{"class":197},"colour)\n",[142,310,312,315,318,321,325,328,331,334],{"class":72,"line":311},6,[142,313,314],{"class":197},"    picture.save(",[142,316,317],{"class":186},"f",[142,319,320],{"class":151},"\"",[142,322,324],{"class":323},"sSjpA","{",[142,326,327],{"class":197},"name",[142,329,330],{"class":323},"}",[142,332,333],{"class":151},".png\"",[142,335,276],{"class":197},[128,337,339],{"id":338},"step-1-embed-an-image-in-a-cell","Step 1 — Embed an image in a cell",[10,341,342,345,346,349],{},[19,343,344],{},"embed_image(row, col, source, options)"," takes zero-based row and column numbers (or an ",[19,347,348],{},"A1","-style reference) and a filename. The image is\nscaled to fit the cell while keeping its aspect ratio, so the cell's size decides how large it appears.",[133,351,353],{"className":177,"code":352,"language":179,"meta":138,"style":138},"import xlsxwriter\n\nworkbook = xlsxwriter.Workbook(\"catalog.xlsx\")\nsheet = workbook.add_worksheet(\"Products\")\nheader = workbook.add_format({\"bold\": True, \"bottom\": 1})\n\nsheet.write_row(0, 0, [\"SKU\", \"Name\", \"Price\", \"Photo\"], header)\nsheet.set_column(\"A:C\", 14)\nsheet.set_column(\"D:D\", 12)\n\nproducts = [(\"W-100\", \"Widget\", 19.99, \"widget.png\"), (\"G-200\", \"Gadget\", 34.50, \"gadget.png\")]\nfor row, (sku, name, price, photo) in enumerate(products, start=1):\n    sheet.set_row(row, 60)                     # height in points; the picture fits inside\n    sheet.write_row(row, 0, [sku, name, price])\n    sheet.embed_image(row, 3, photo, {\"description\": f\"{name} product photo\"})\n\nworkbook.close()\n",[19,354,355,363,367,382,397,429,433,469,484,499,504,555,581,597,608,640,645],{"__ignoreMap":138},[142,356,357,360],{"class":72,"line":144},[142,358,359],{"class":186},"import",[142,361,362],{"class":197}," xlsxwriter\n",[142,364,365],{"class":72,"line":201},[142,366,205],{"emptyLinePlaceholder":204},[142,368,369,372,374,377,380],{"class":72,"line":208},[142,370,371],{"class":197},"workbook ",[142,373,251],{"class":186},[142,375,376],{"class":197}," xlsxwriter.Workbook(",[142,378,379],{"class":151},"\"catalog.xlsx\"",[142,381,276],{"class":197},[142,383,384,387,389,392,395],{"class":72,"line":245},[142,385,386],{"class":197},"sheet ",[142,388,251],{"class":186},[142,390,391],{"class":197}," workbook.add_worksheet(",[142,393,394],{"class":151},"\"Products\"",[142,396,276],{"class":197},[142,398,399,402,404,407,410,413,416,418,421,423,426],{"class":72,"line":279},[142,400,401],{"class":197},"header ",[142,403,251],{"class":186},[142,405,406],{"class":197}," workbook.add_format({",[142,408,409],{"class":151},"\"bold\"",[142,411,412],{"class":197},": ",[142,414,415],{"class":190},"True",[142,417,225],{"class":197},[142,419,420],{"class":151},"\"bottom\"",[142,422,412],{"class":197},[142,424,425],{"class":190},"1",[142,427,428],{"class":197},"})\n",[142,430,431],{"class":72,"line":311},[142,432,205],{"emptyLinePlaceholder":204},[142,434,436,439,441,443,445,448,451,453,456,458,461,463,466],{"class":72,"line":435},7,[142,437,438],{"class":197},"sheet.write_row(",[142,440,51],{"class":190},[142,442,225],{"class":197},[142,444,51],{"class":190},[142,446,447],{"class":197},", [",[142,449,450],{"class":151},"\"SKU\"",[142,452,225],{"class":197},[142,454,455],{"class":151},"\"Name\"",[142,457,225],{"class":197},[142,459,460],{"class":151},"\"Price\"",[142,462,225],{"class":197},[142,464,465],{"class":151},"\"Photo\"",[142,467,468],{"class":197},"], header)\n",[142,470,472,475,478,480,482],{"class":72,"line":471},8,[142,473,474],{"class":197},"sheet.set_column(",[142,476,477],{"class":151},"\"A:C\"",[142,479,225],{"class":197},[142,481,60],{"class":190},[142,483,276],{"class":197},[142,485,487,489,492,494,497],{"class":72,"line":486},9,[142,488,474],{"class":197},[142,490,491],{"class":151},"\"D:D\"",[142,493,225],{"class":197},[142,495,496],{"class":190},"12",[142,498,276],{"class":197},[142,500,502],{"class":72,"line":501},10,[142,503,205],{"emptyLinePlaceholder":204},[142,505,507,510,512,514,517,519,522,524,527,529,532,534,537,539,542,544,547,549,552],{"class":72,"line":506},11,[142,508,509],{"class":197},"products ",[142,511,251],{"class":186},[142,513,219],{"class":197},[142,515,516],{"class":151},"\"W-100\"",[142,518,225],{"class":197},[142,520,521],{"class":151},"\"Widget\"",[142,523,225],{"class":197},[142,525,526],{"class":190},"19.99",[142,528,225],{"class":197},[142,530,531],{"class":151},"\"widget.png\"",[142,533,231],{"class":197},[142,535,536],{"class":151},"\"G-200\"",[142,538,225],{"class":197},[142,540,541],{"class":151},"\"Gadget\"",[142,543,225],{"class":197},[142,545,546],{"class":190},"34.50",[142,548,225],{"class":197},[142,550,551],{"class":151},"\"gadget.png\"",[142,553,554],{"class":197},")]\n",[142,556,558,560,563,565,568,571,574,576,578],{"class":72,"line":557},12,[142,559,211],{"class":186},[142,561,562],{"class":197}," row, (sku, name, price, photo) ",[142,564,16],{"class":186},[142,566,567],{"class":190}," enumerate",[142,569,570],{"class":197},"(products, ",[142,572,573],{"class":302},"start",[142,575,251],{"class":186},[142,577,425],{"class":190},[142,579,580],{"class":197},"):\n",[142,582,584,587,590,593],{"class":72,"line":583},13,[142,585,586],{"class":197},"    sheet.set_row(row, ",[142,588,589],{"class":190},"60",[142,591,592],{"class":197},")                     ",[142,594,596],{"class":595},"s-wDw","# height in points; the picture fits inside\n",[142,598,600,603,605],{"class":72,"line":599},14,[142,601,602],{"class":197},"    sheet.write_row(row, ",[142,604,51],{"class":190},[142,606,607],{"class":197},", [sku, name, price])\n",[142,609,611,614,617,620,623,625,627,629,631,633,635,638],{"class":72,"line":610},15,[142,612,613],{"class":197},"    sheet.embed_image(row, ",[142,615,616],{"class":190},"3",[142,618,619],{"class":197},", photo, {",[142,621,622],{"class":151},"\"description\"",[142,624,412],{"class":197},[142,626,317],{"class":186},[142,628,320],{"class":151},[142,630,324],{"class":323},[142,632,327],{"class":197},[142,634,330],{"class":323},[142,636,637],{"class":151}," product photo\"",[142,639,428],{"class":197},[142,641,643],{"class":72,"line":642},16,[142,644,205],{"emptyLinePlaceholder":204},[142,646,648],{"class":72,"line":647},17,[142,649,650],{"class":197},"workbook.close()\n",[10,652,653,654,657],{},"Setting the row height before embedding is what makes the result look deliberate. A default-height row produces a thumbnail about the size of a\nletter; 60 points gives a readable picture without making the table unwieldy. The ",[19,655,656],{},"description"," becomes the image's alternative text for screen\nreaders, which is worth filling in for any report that is shared widely.",[128,659,661],{"id":660},"step-2-size-rows-and-columns-for-the-pictures","Step 2 — Size rows and columns for the pictures",[10,663,664],{},"Because an embedded picture fits itself to its cell, sizing is entirely a question of column width and row height. Column width is measured in\ncharacter units and row height in points, so a square cell needs a little arithmetic: at default font settings one character unit is roughly seven\npixels and one point is four-thirds of a pixel.",[133,666,668],{"className":177,"code":667,"language":179,"meta":138,"style":138},"def square_cell(sheet, row: int, col: int, pixels: int) -> None:\n    sheet.set_column(col, col, pixels \u002F 7)        # approximate character units\n    sheet.set_row(row, pixels * 0.75)             # points\n\nworkbook = xlsxwriter.Workbook(\"square.xlsx\")\nsheet = workbook.add_worksheet()\nfor row in range(1, 3):\n    square_cell(sheet, row, 1, 90)\nsheet.embed_image(1, 1, \"widget.png\")\nsheet.embed_image(2, 1, \"gadget.png\")\nworkbook.close()\n",[19,669,670,704,721,738,742,755,764,787,801,818,835],{"__ignoreMap":138},[142,671,672,675,679,682,685,688,690,693,695,698,701],{"class":72,"line":144},[142,673,674],{"class":186},"def",[142,676,678],{"class":677},"s_Opv"," square_cell",[142,680,681],{"class":197},"(sheet, row: ",[142,683,684],{"class":190},"int",[142,686,687],{"class":197},", col: ",[142,689,684],{"class":190},[142,691,692],{"class":197},", pixels: ",[142,694,684],{"class":190},[142,696,697],{"class":197},") -> ",[142,699,700],{"class":190},"None",[142,702,703],{"class":197},":\n",[142,705,706,709,712,715,718],{"class":72,"line":201},[142,707,708],{"class":197},"    sheet.set_column(col, col, pixels ",[142,710,711],{"class":186},"\u002F",[142,713,714],{"class":190}," 7",[142,716,717],{"class":197},")        ",[142,719,720],{"class":595},"# approximate character units\n",[142,722,723,726,729,732,735],{"class":72,"line":208},[142,724,725],{"class":197},"    sheet.set_row(row, pixels ",[142,727,728],{"class":186},"*",[142,730,731],{"class":190}," 0.75",[142,733,734],{"class":197},")             ",[142,736,737],{"class":595},"# points\n",[142,739,740],{"class":72,"line":245},[142,741,205],{"emptyLinePlaceholder":204},[142,743,744,746,748,750,753],{"class":72,"line":279},[142,745,371],{"class":197},[142,747,251],{"class":186},[142,749,376],{"class":197},[142,751,752],{"class":151},"\"square.xlsx\"",[142,754,276],{"class":197},[142,756,757,759,761],{"class":72,"line":311},[142,758,386],{"class":197},[142,760,251],{"class":186},[142,762,763],{"class":197}," workbook.add_worksheet()\n",[142,765,766,768,771,773,776,779,781,783,785],{"class":72,"line":435},[142,767,211],{"class":186},[142,769,770],{"class":197}," row ",[142,772,16],{"class":186},[142,774,775],{"class":190}," range",[142,777,778],{"class":197},"(",[142,780,425],{"class":190},[142,782,225],{"class":197},[142,784,616],{"class":190},[142,786,580],{"class":197},[142,788,789,792,794,796,799],{"class":72,"line":471},[142,790,791],{"class":197},"    square_cell(sheet, row, ",[142,793,425],{"class":190},[142,795,225],{"class":197},[142,797,798],{"class":190},"90",[142,800,276],{"class":197},[142,802,803,806,808,810,812,814,816],{"class":72,"line":486},[142,804,805],{"class":197},"sheet.embed_image(",[142,807,425],{"class":190},[142,809,225],{"class":197},[142,811,425],{"class":190},[142,813,225],{"class":197},[142,815,531],{"class":151},[142,817,276],{"class":197},[142,819,820,822,825,827,829,831,833],{"class":72,"line":501},[142,821,805],{"class":197},[142,823,824],{"class":190},"2",[142,826,225],{"class":197},[142,828,425],{"class":190},[142,830,225],{"class":197},[142,832,551],{"class":151},[142,834,276],{"class":197},[142,836,837],{"class":72,"line":506},[142,838,650],{"class":197},[10,840,841,842,845,846,850],{},"The picture keeps its proportions inside a non-square cell, leaving blank space on the longer side. For consistent results, pre-process source images to\nthe same aspect ratio before embedding — cropping product photos to squares is a two-line job with Pillow's ",[19,843,844],{},"ImageOps.fit",". The general column and row\nsizing rules are in ",[24,847,849],{"href":848},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fstyling-excel-cells-with-openpyxl\u002Fset-column-width-and-row-height-in-openpyxl\u002F","Set Column Width and Row Height in openpyxl",".",[30,852,39,858,39,861,39,864,39,868,39,873,39,876,39,882,39,886,39,890,39,893,39,897,39,900,39,904,39,907,39,910,39,912,39,916,39,918,39,921,39,923,39,926,39,928,39,931,39,933,39,936,39,938,39,941,39,943,39,946,39,948,39,950,39,952,39,956,39,963,39,968,39,971,39,974,39,976,39,979,39,981,39,984,39,986,39,988,39,992,39,995,39,998,39,1001,39,1003,39,1006,39,1008,39,1011,39,1013,39,1016,39,1018,39,1021,39,1024,39,1028],{"viewBox":853,"role":33,"ariaLabelledBy":854,"xmlns":37,"style":857},"0 0 556 224",[855,856],"emb-grid-t","emb-grid-d","width:100%;max-width:556px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[41,859,860],{"id":855},"A catalogue table with a picture in each row",[45,862,863],{"id":856},"Columns A to C hold SKU, name and price; column D holds an embedded photo. Rows are 60 points tall so the pictures are legible, and sorting by price moves each photo with its product.",[49,865],{"x":51,"y":51,"width":866,"height":867,"fill":54},"556","224",[49,869],{"x":57,"y":57,"width":74,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},"30","#e7ebef","var(--line,#cdd5e6)",[49,874],{"x":75,"y":57,"width":875,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},"70",[65,877,881],{"x":878,"y":879,"style":880},"91","40","font-size:11.5px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:middle","A",[49,883],{"x":884,"y":57,"width":885,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},"126","80",[65,887,889],{"x":888,"y":879,"style":880},"166","B",[49,891],{"x":892,"y":57,"width":589,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},"206",[65,894,896],{"x":895,"y":879,"style":880},"236","C",[49,898],{"x":899,"y":57,"width":798,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},"266",[65,901,903],{"x":902,"y":879,"style":880},"311","D",[49,905],{"x":57,"y":906,"width":74,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},"50",[65,908,425],{"x":909,"y":875,"style":880},"38",[49,911],{"x":75,"y":906,"width":875,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},[65,913,915],{"x":878,"y":875,"style":914},"font-size:11.5px;font-weight:400;fill:var(--muted,#5b6780);text-anchor:middle","SKU",[49,917],{"x":884,"y":906,"width":885,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},[65,919,920],{"x":888,"y":875,"style":914},"Name",[49,922],{"x":892,"y":906,"width":589,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},[65,924,925],{"x":895,"y":875,"style":914},"Price",[49,927],{"x":899,"y":906,"width":798,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},[65,929,930],{"x":902,"y":875,"style":914},"Photo",[49,932],{"x":57,"y":885,"width":74,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},[65,934,824],{"x":909,"y":935,"style":880},"100",[49,937],{"x":75,"y":885,"width":875,"height":870,"rx":51,"fill":54,"stroke":872,"style":77},[65,939,940],{"x":878,"y":935,"style":81},"W-100",[49,942],{"x":884,"y":885,"width":885,"height":870,"rx":51,"fill":54,"stroke":872,"style":77},[65,944,945],{"x":888,"y":935,"style":81},"Widget",[49,947],{"x":892,"y":885,"width":589,"height":870,"rx":51,"fill":54,"stroke":872,"style":77},[65,949,526],{"x":895,"y":935,"style":81},[49,951],{"x":899,"y":885,"width":798,"height":870,"rx":51,"fill":98,"stroke":99,"style":77},[65,953,955],{"x":902,"y":935,"style":954},"font-size:11.5px;font-weight:600;fill:var(--teal-ink,#0b6157);text-anchor:middle","[picture]",[49,957],{"x":958,"y":959,"width":960,"height":961,"rx":962,"fill":871,"stroke":872,"style":77},"376","82","160","26","8",[65,964,967],{"x":965,"y":966,"style":880},"456","99","row height 60 pt",[49,969],{"x":57,"y":970,"width":74,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},"110",[65,972,616],{"x":909,"y":973,"style":880},"130",[49,975],{"x":75,"y":970,"width":875,"height":870,"rx":51,"fill":54,"stroke":872,"style":77},[65,977,978],{"x":878,"y":973,"style":81},"G-200",[49,980],{"x":884,"y":970,"width":885,"height":870,"rx":51,"fill":54,"stroke":872,"style":77},[65,982,983],{"x":888,"y":973,"style":81},"Gadget",[49,985],{"x":892,"y":970,"width":589,"height":870,"rx":51,"fill":54,"stroke":872,"style":77},[65,987,546],{"x":895,"y":973,"style":81},[49,989],{"x":899,"y":970,"width":798,"height":870,"rx":51,"fill":990,"stroke":991,"style":77},"#f0f4ff","var(--brand,#5b5cf0)",[65,993,955],{"x":902,"y":973,"style":994},"font-size:11.5px;font-weight:600;fill:var(--brand-strong,#4338ca);text-anchor:middle",[49,996],{"x":57,"y":997,"width":74,"height":870,"rx":51,"fill":871,"stroke":872,"style":77},"140",[65,999,1000],{"x":909,"y":960,"style":880},"4",[49,1002],{"x":75,"y":997,"width":875,"height":870,"rx":51,"fill":54,"stroke":872,"style":77},[65,1004,1005],{"x":878,"y":960,"style":81},"T-300",[49,1007],{"x":884,"y":997,"width":885,"height":870,"rx":51,"fill":54,"stroke":872,"style":77},[65,1009,1010],{"x":888,"y":960,"style":81},"Tool",[49,1012],{"x":892,"y":997,"width":589,"height":870,"rx":51,"fill":54,"stroke":872,"style":77},[65,1014,1015],{"x":895,"y":960,"style":81},"12.00",[49,1017],{"x":899,"y":997,"width":798,"height":870,"rx":51,"fill":61,"stroke":62,"style":77},[65,1019,955],{"x":902,"y":960,"style":1020},"font-size:11.5px;font-weight:600;fill:var(--gold-ink,#7a4e06);text-anchor:middle",[49,1022],{"x":958,"y":1023,"width":960,"height":961,"rx":962,"fill":98,"stroke":99,"style":77},"142",[65,1025,1027],{"x":965,"y":1026,"style":954},"159","sorts with its row",[65,1029,1032],{"x":1030,"y":1031,"style":125},"278","202","the picture is the cell value, so it travels with the row",[128,1034,1036],{"id":1035},"step-3-embed-images-from-bytes","Step 3 — Embed images from bytes",[10,1038,1039,1040,1043,1044,1047],{},"Reports rarely have image files lying on disk. Photos come from a database, an object store or an HTTP API, and writing them to temporary files just to\nembed them is wasteful. Pass a ",[19,1041,1042],{},"BytesIO"," object as ",[19,1045,1046],{},"image_data"," in the options, together with a filename argument that only serves to identify the\nimage type.",[133,1049,1051],{"className":177,"code":1050,"language":179,"meta":138,"style":138},"from io import BytesIO\n\ndef png_bytes(colour: str) -> BytesIO:\n    picture = Image.new(\"RGB\", (240, 240), \"white\")\n    ImageDraw.Draw(picture).rectangle((30, 30, 210, 210), fill=colour)\n    buffer = BytesIO()\n    picture.save(buffer, format=\"PNG\")\n    buffer.seek(0)\n    return buffer\n\nworkbook = xlsxwriter.Workbook(\"from_bytes.xlsx\")\nsheet = workbook.add_worksheet()\nsheet.set_column(\"B:B\", 12)\nfor row, colour in enumerate([\"#f43f8f\", \"#b4740a\", \"#0f9488\"], start=1):\n    sheet.set_row(row, 60)\n    sheet.write(row, 0, colour)\n    sheet.embed_image(row, 1, f\"swatch{row}.png\", {\"image_data\": png_bytes(colour)})\nworkbook.close()\n",[19,1052,1053,1065,1069,1085,1109,1137,1147,1162,1171,1179,1183,1196,1204,1217,1254,1262,1272,1303],{"__ignoreMap":138},[142,1054,1055,1057,1060,1062],{"class":72,"line":144},[142,1056,187],{"class":186},[142,1058,1059],{"class":197}," io ",[142,1061,359],{"class":186},[142,1063,1064],{"class":197}," BytesIO\n",[142,1066,1067],{"class":72,"line":201},[142,1068,205],{"emptyLinePlaceholder":204},[142,1070,1071,1073,1076,1079,1082],{"class":72,"line":208},[142,1072,674],{"class":186},[142,1074,1075],{"class":677}," png_bytes",[142,1077,1078],{"class":197},"(colour: ",[142,1080,1081],{"class":190},"str",[142,1083,1084],{"class":197},") -> BytesIO:\n",[142,1086,1087,1089,1091,1093,1095,1097,1099,1101,1103,1105,1107],{"class":72,"line":245},[142,1088,248],{"class":197},[142,1090,251],{"class":186},[142,1092,254],{"class":197},[142,1094,257],{"class":151},[142,1096,260],{"class":197},[142,1098,263],{"class":190},[142,1100,225],{"class":197},[142,1102,263],{"class":190},[142,1104,270],{"class":197},[142,1106,273],{"class":151},[142,1108,276],{"class":197},[142,1110,1111,1114,1116,1118,1120,1122,1125,1127,1129,1131,1133,1135],{"class":72,"line":279},[142,1112,1113],{"class":197},"    ImageDraw.Draw(picture).rectangle((",[142,1115,870],{"class":190},[142,1117,225],{"class":197},[142,1119,870],{"class":190},[142,1121,225],{"class":197},[142,1123,1124],{"class":190},"210",[142,1126,225],{"class":197},[142,1128,1124],{"class":190},[142,1130,270],{"class":197},[142,1132,303],{"class":302},[142,1134,251],{"class":186},[142,1136,308],{"class":197},[142,1138,1139,1142,1144],{"class":72,"line":311},[142,1140,1141],{"class":197},"    buffer ",[142,1143,251],{"class":186},[142,1145,1146],{"class":197}," BytesIO()\n",[142,1148,1149,1152,1155,1157,1160],{"class":72,"line":435},[142,1150,1151],{"class":197},"    picture.save(buffer, ",[142,1153,1154],{"class":302},"format",[142,1156,251],{"class":186},[142,1158,1159],{"class":151},"\"PNG\"",[142,1161,276],{"class":197},[142,1163,1164,1167,1169],{"class":72,"line":471},[142,1165,1166],{"class":197},"    buffer.seek(",[142,1168,51],{"class":190},[142,1170,276],{"class":197},[142,1172,1173,1176],{"class":72,"line":486},[142,1174,1175],{"class":186},"    return",[142,1177,1178],{"class":197}," buffer\n",[142,1180,1181],{"class":72,"line":501},[142,1182,205],{"emptyLinePlaceholder":204},[142,1184,1185,1187,1189,1191,1194],{"class":72,"line":506},[142,1186,371],{"class":197},[142,1188,251],{"class":186},[142,1190,376],{"class":197},[142,1192,1193],{"class":151},"\"from_bytes.xlsx\"",[142,1195,276],{"class":197},[142,1197,1198,1200,1202],{"class":72,"line":557},[142,1199,386],{"class":197},[142,1201,251],{"class":186},[142,1203,763],{"class":197},[142,1205,1206,1208,1211,1213,1215],{"class":72,"line":583},[142,1207,474],{"class":197},[142,1209,1210],{"class":151},"\"B:B\"",[142,1212,225],{"class":197},[142,1214,496],{"class":190},[142,1216,276],{"class":197},[142,1218,1219,1221,1224,1226,1228,1231,1234,1236,1239,1241,1243,1246,1248,1250,1252],{"class":72,"line":599},[142,1220,211],{"class":186},[142,1222,1223],{"class":197}," row, colour ",[142,1225,16],{"class":186},[142,1227,567],{"class":190},[142,1229,1230],{"class":197},"([",[142,1232,1233],{"class":151},"\"#f43f8f\"",[142,1235,225],{"class":197},[142,1237,1238],{"class":151},"\"#b4740a\"",[142,1240,225],{"class":197},[142,1242,228],{"class":151},[142,1244,1245],{"class":197},"], ",[142,1247,573],{"class":302},[142,1249,251],{"class":186},[142,1251,425],{"class":190},[142,1253,580],{"class":197},[142,1255,1256,1258,1260],{"class":72,"line":610},[142,1257,586],{"class":197},[142,1259,589],{"class":190},[142,1261,276],{"class":197},[142,1263,1264,1267,1269],{"class":72,"line":642},[142,1265,1266],{"class":197},"    sheet.write(row, ",[142,1268,51],{"class":190},[142,1270,1271],{"class":197},", colour)\n",[142,1273,1274,1276,1278,1280,1282,1285,1287,1290,1292,1294,1297,1300],{"class":72,"line":647},[142,1275,613],{"class":197},[142,1277,425],{"class":190},[142,1279,225],{"class":197},[142,1281,317],{"class":186},[142,1283,1284],{"class":151},"\"swatch",[142,1286,324],{"class":323},[142,1288,1289],{"class":197},"row",[142,1291,330],{"class":323},[142,1293,333],{"class":151},[142,1295,1296],{"class":197},", {",[142,1298,1299],{"class":151},"\"image_data\"",[142,1301,1302],{"class":197},": png_bytes(colour)})\n",[142,1304,1306],{"class":72,"line":1305},18,[142,1307,650],{"class":197},[10,1309,1310,1311,1313,1314,850],{},"xlsxwriter stores each distinct image once, even when it is embedded in many cells, so a status icon repeated down a column of thousands of rows adds\nonly one copy of the picture to the file. The same ",[19,1312,1042],{}," approach works for matplotlib figures, as shown in\n",[24,1315,1317],{"href":1316},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-a-matplotlib-chart-in-an-excel-report\u002F","Embed a matplotlib Chart in an Excel Report",[128,1319,1321],{"id":1320},"step-4-link-an-embedded-image","Step 4 — Link an embedded image",[10,1323,1324,1325,1328,1329,850],{},"Adding a ",[19,1326,1327],{},"url"," option makes the cell a hyperlink as well as a picture — useful for linking a thumbnail to a full-size photo or a product page. xlsxwriter\napplies its default hyperlink format unless you pass a ",[19,1330,1331],{},"cell_format",[133,1333,1335],{"className":177,"code":1334,"language":179,"meta":138,"style":138},"workbook = xlsxwriter.Workbook(\"linked.xlsx\")\nsheet = workbook.add_worksheet()\nsheet.set_row(1, 60)\nsheet.set_column(\"A:A\", 12)\nsheet.embed_image(1, 0, \"widget.png\", {\n    \"url\": \"https:\u002F\u002Fexample.com\u002Fproducts\u002FW-100\",\n    \"description\": \"Widget product photo, links to the product page\",\n})\nworkbook.close()\n",[19,1336,1337,1350,1358,1371,1384,1401,1414,1426,1430],{"__ignoreMap":138},[142,1338,1339,1341,1343,1345,1348],{"class":72,"line":144},[142,1340,371],{"class":197},[142,1342,251],{"class":186},[142,1344,376],{"class":197},[142,1346,1347],{"class":151},"\"linked.xlsx\"",[142,1349,276],{"class":197},[142,1351,1352,1354,1356],{"class":72,"line":201},[142,1353,386],{"class":197},[142,1355,251],{"class":186},[142,1357,763],{"class":197},[142,1359,1360,1363,1365,1367,1369],{"class":72,"line":208},[142,1361,1362],{"class":197},"sheet.set_row(",[142,1364,425],{"class":190},[142,1366,225],{"class":197},[142,1368,589],{"class":190},[142,1370,276],{"class":197},[142,1372,1373,1375,1378,1380,1382],{"class":72,"line":245},[142,1374,474],{"class":197},[142,1376,1377],{"class":151},"\"A:A\"",[142,1379,225],{"class":197},[142,1381,496],{"class":190},[142,1383,276],{"class":197},[142,1385,1386,1388,1390,1392,1394,1396,1398],{"class":72,"line":279},[142,1387,805],{"class":197},[142,1389,425],{"class":190},[142,1391,225],{"class":197},[142,1393,51],{"class":190},[142,1395,225],{"class":197},[142,1397,531],{"class":151},[142,1399,1400],{"class":197},", {\n",[142,1402,1403,1406,1408,1411],{"class":72,"line":311},[142,1404,1405],{"class":151},"    \"url\"",[142,1407,412],{"class":197},[142,1409,1410],{"class":151},"\"https:\u002F\u002Fexample.com\u002Fproducts\u002FW-100\"",[142,1412,1413],{"class":197},",\n",[142,1415,1416,1419,1421,1424],{"class":72,"line":435},[142,1417,1418],{"class":151},"    \"description\"",[142,1420,412],{"class":197},[142,1422,1423],{"class":151},"\"Widget product photo, links to the product page\"",[142,1425,1413],{"class":197},[142,1427,1428],{"class":72,"line":471},[142,1429,428],{"class":197},[142,1431,1432],{"class":72,"line":486},[142,1433,650],{"class":197},[10,1435,1436,1437,850],{},"Hyperlinks in general, including links to other sheets and cells, are covered in\n",[24,1438,1440],{"href":1439},"\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",[128,1442,1444],{"id":1443},"step-5-plan-for-readers-and-tools-that-do-not-support-it","Step 5 — Plan for readers and tools that do not support it",[10,1446,1447],{},"A picture in a cell is stored as a rich value, a newer part of the file format. Three consequences follow, and each is worth deciding about before a\nreport goes out.",[1449,1450,1451,1461,1467],"ul",{},[1452,1453,1454,1460],"li",{},[1455,1456,1457,1458],"strong",{},"Older Excel versions show ",[19,1459,173],{}," in those cells, because xlsxwriter stores that error as the fallback value. If your readers include people on\nperpetual-licence Excel, use floating images instead.",[1452,1462,1463,1466],{},[1455,1464,1465],{},"pandas reads nothing"," for those cells: they come back as missing values, so an embedded-image column never pollutes data reads.",[1452,1468,1469,1472,1473,1475],{},[1455,1470,1471],{},"openpyxl drops embedded pictures"," when it loads and re-saves the workbook. It sees ",[19,1474,173],{}," in the cell and does not keep the rich value parts, so any\npost-processing step must happen before xlsxwriter writes the file, not after.",[133,1477,1479],{"className":177,"code":1478,"language":179,"meta":138,"style":138},"import pandas as pd\nfrom openpyxl import load_workbook\n\nprint(pd.read_excel(\"catalog.xlsx\"))                 # Photo column is NaN\nprint(load_workbook(\"catalog.xlsx\")[\"Products\"][\"D2\"].value)   # '#VALUE!'\n",[19,1480,1481,1494,1506,1510,1526],{"__ignoreMap":138},[142,1482,1483,1485,1488,1491],{"class":72,"line":144},[142,1484,359],{"class":186},[142,1486,1487],{"class":197}," pandas ",[142,1489,1490],{"class":186},"as",[142,1492,1493],{"class":197}," pd\n",[142,1495,1496,1498,1501,1503],{"class":72,"line":201},[142,1497,187],{"class":186},[142,1499,1500],{"class":197}," openpyxl ",[142,1502,359],{"class":186},[142,1504,1505],{"class":197}," load_workbook\n",[142,1507,1508],{"class":72,"line":208},[142,1509,205],{"emptyLinePlaceholder":204},[142,1511,1512,1515,1518,1520,1523],{"class":72,"line":245},[142,1513,1514],{"class":190},"print",[142,1516,1517],{"class":197},"(pd.read_excel(",[142,1519,379],{"class":151},[142,1521,1522],{"class":197},"))                 ",[142,1524,1525],{"class":595},"# Photo column is NaN\n",[142,1527,1528,1530,1533,1535,1538,1540,1543,1546,1549],{"class":72,"line":279},[142,1529,1514],{"class":190},[142,1531,1532],{"class":197},"(load_workbook(",[142,1534,379],{"class":151},[142,1536,1537],{"class":197},")[",[142,1539,394],{"class":151},[142,1541,1542],{"class":197},"][",[142,1544,1545],{"class":151},"\"D2\"",[142,1547,1548],{"class":197},"].value)   ",[142,1550,1551],{"class":595},"# '#VALUE!'\n",[30,1553,39,1559,39,1562,39,1565,39,1569,39,1573,39,1578,39,1584,39,1588,39,1595,39,1600,39,1602,39,1606,39,1608,39,1612,39,1615,39,1618,39,1622,39,1625,39,1629,39,1633,39,1636,39,1640,39,1643,39,1649,39,1653],{"viewBox":1554,"role":33,"ariaLabelledBy":1555,"xmlns":37,"style":1558},"0 0 720 256",[1556,1557],"emb-compat-t","emb-compat-d","width:100%;max-width:720px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif",[41,1560,1561],{"id":1556},"How different readers see an embedded image cell",[45,1563,1564],{"id":1557},"Current Microsoft 365 Excel shows the picture. Older Excel versions show the VALUE error. pandas reads a missing value. openpyxl reads the VALUE error string and loses the picture if it saves the file.",[49,1566],{"x":51,"y":51,"width":1567,"height":1568,"fill":54},"720","256",[65,1570,1572],{"x":57,"y":870,"style":1571},"font-size:12px;font-weight:600;fill:var(--muted,#5b6780);text-anchor:start","what each reader gets from the Photo column",[49,1574],{"x":57,"y":68,"width":1575,"height":1576,"rx":1577,"fill":54,"stroke":872,"style":77},"190","28","6",[65,1579,1583],{"x":1580,"y":1581,"style":1582},"115","65","font-size:12px;font-weight:600;fill:var(--text,#172033);text-anchor:middle","Excel for Microsoft 365",[49,1585],{"x":867,"y":1586,"width":1587,"height":961,"rx":1577,"fill":871,"stroke":872,"style":77},"47","330",[49,1589],{"x":1590,"y":1591,"width":1592,"height":1593,"rx":1594,"fill":98,"stroke":99,"style":77},"225","48","311.5","24","5",[65,1596,1599],{"x":1597,"y":1581,"style":1598},"566","font-size:12px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:start","the picture",[49,1601],{"x":57,"y":798,"width":1575,"height":1576,"rx":1577,"fill":54,"stroke":872,"style":77},[65,1603,1605],{"x":1580,"y":1604,"style":1582},"109","older Excel versions",[49,1607],{"x":867,"y":878,"width":1587,"height":961,"rx":1577,"fill":871,"stroke":872,"style":77},[49,1609],{"x":1590,"y":1610,"width":1611,"height":1593,"rx":1594,"fill":61,"stroke":62,"style":77},"92","163",[65,1613,173],{"x":1597,"y":1604,"style":1614},"font-size:12px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:start",[49,1616],{"x":57,"y":1617,"width":1575,"height":1576,"rx":1577,"fill":54,"stroke":872,"style":77},"134",[65,1619,1621],{"x":1580,"y":1620,"style":1582},"153","pandas read_excel",[49,1623],{"x":867,"y":1624,"width":1587,"height":961,"rx":1577,"fill":871,"stroke":872,"style":77},"135",[49,1626],{"x":1590,"y":1627,"width":1628,"height":1593,"rx":1594,"fill":871,"stroke":872,"style":77},"136","97",[65,1630,1632],{"x":1597,"y":1620,"style":1631},"font-size:12px;font-weight:700;fill:var(--muted,#5b6780);text-anchor:start","NaN",[49,1634],{"x":57,"y":1635,"width":1575,"height":1576,"rx":1577,"fill":54,"stroke":872,"style":77},"178",[65,1637,1639],{"x":1580,"y":1638,"style":1582},"197","openpyxl load + save",[49,1641],{"x":867,"y":1642,"width":1587,"height":961,"rx":1577,"fill":871,"stroke":872,"style":77},"179",[49,1644],{"x":1590,"y":1645,"width":1646,"height":1593,"rx":1594,"fill":1647,"stroke":1648,"style":77},"180","31","#fee8f2","var(--accent,#f43f8f)",[65,1650,1652],{"x":1597,"y":1638,"style":1651},"font-size:12px;font-weight:700;fill:var(--accent-ink,#be185d);text-anchor:start","picture lost",[65,1654,1657],{"x":1655,"y":1656,"style":125},"360","238","write with xlsxwriter last; never round-trip through openpyxl",[128,1659,1661],{"id":1660},"step-6-use-floating-images-where-they-fit-better","Step 6 — Use floating images where they fit better",[10,1663,1664,1665,1668,1669,1672,1673,1675,1676,1678,1679,1681],{},"Floating images from ",[19,1666,1667],{},"insert_image"," remain the right tool for anything that does not belong to a row: a logo in the header area, a chart image beside a\ntable, a signature block. Their ",[19,1670,1671],{},"object_position"," option controls how they respond to row and column changes — ",[19,1674,425],{}," moves and sizes with cells, ",[19,1677,824],{}," moves\nbut does not size, and ",[19,1680,616],{}," neither moves nor sizes.",[133,1683,1685],{"className":177,"code":1684,"language":179,"meta":138,"style":138},"workbook = xlsxwriter.Workbook(\"mixed.xlsx\")\nsheet = workbook.add_worksheet()\nsheet.set_row(0, 50)\nsheet.insert_image(\"A1\", \"gadget.png\", {\"x_scale\": 0.2, \"y_scale\": 0.2, \"object_position\": 3})\nsheet.write(\"C1\", \"Quarterly product catalogue\")\nsheet.set_row(2, 60)\nsheet.set_column(\"D:D\", 12)\nsheet.write_row(2, 0, [\"W-100\", \"Widget\", 19.99])\nsheet.embed_image(2, 3, \"widget.png\")\nworkbook.close()\n",[19,1686,1687,1700,1708,1720,1762,1777,1789,1801,1826,1842],{"__ignoreMap":138},[142,1688,1689,1691,1693,1695,1698],{"class":72,"line":144},[142,1690,371],{"class":197},[142,1692,251],{"class":186},[142,1694,376],{"class":197},[142,1696,1697],{"class":151},"\"mixed.xlsx\"",[142,1699,276],{"class":197},[142,1701,1702,1704,1706],{"class":72,"line":201},[142,1703,386],{"class":197},[142,1705,251],{"class":186},[142,1707,763],{"class":197},[142,1709,1710,1712,1714,1716,1718],{"class":72,"line":208},[142,1711,1362],{"class":197},[142,1713,51],{"class":190},[142,1715,225],{"class":197},[142,1717,906],{"class":190},[142,1719,276],{"class":197},[142,1721,1722,1725,1728,1730,1732,1734,1737,1739,1742,1744,1747,1749,1751,1753,1756,1758,1760],{"class":72,"line":245},[142,1723,1724],{"class":197},"sheet.insert_image(",[142,1726,1727],{"class":151},"\"A1\"",[142,1729,225],{"class":197},[142,1731,551],{"class":151},[142,1733,1296],{"class":197},[142,1735,1736],{"class":151},"\"x_scale\"",[142,1738,412],{"class":197},[142,1740,1741],{"class":190},"0.2",[142,1743,225],{"class":197},[142,1745,1746],{"class":151},"\"y_scale\"",[142,1748,412],{"class":197},[142,1750,1741],{"class":190},[142,1752,225],{"class":197},[142,1754,1755],{"class":151},"\"object_position\"",[142,1757,412],{"class":197},[142,1759,616],{"class":190},[142,1761,428],{"class":197},[142,1763,1764,1767,1770,1772,1775],{"class":72,"line":279},[142,1765,1766],{"class":197},"sheet.write(",[142,1768,1769],{"class":151},"\"C1\"",[142,1771,225],{"class":197},[142,1773,1774],{"class":151},"\"Quarterly product catalogue\"",[142,1776,276],{"class":197},[142,1778,1779,1781,1783,1785,1787],{"class":72,"line":311},[142,1780,1362],{"class":197},[142,1782,824],{"class":190},[142,1784,225],{"class":197},[142,1786,589],{"class":190},[142,1788,276],{"class":197},[142,1790,1791,1793,1795,1797,1799],{"class":72,"line":435},[142,1792,474],{"class":197},[142,1794,491],{"class":151},[142,1796,225],{"class":197},[142,1798,496],{"class":190},[142,1800,276],{"class":197},[142,1802,1803,1805,1807,1809,1811,1813,1815,1817,1819,1821,1823],{"class":72,"line":471},[142,1804,438],{"class":197},[142,1806,824],{"class":190},[142,1808,225],{"class":197},[142,1810,51],{"class":190},[142,1812,447],{"class":197},[142,1814,516],{"class":151},[142,1816,225],{"class":197},[142,1818,521],{"class":151},[142,1820,225],{"class":197},[142,1822,526],{"class":190},[142,1824,1825],{"class":197},"])\n",[142,1827,1828,1830,1832,1834,1836,1838,1840],{"class":72,"line":486},[142,1829,805],{"class":197},[142,1831,824],{"class":190},[142,1833,225],{"class":197},[142,1835,616],{"class":190},[142,1837,225],{"class":197},[142,1839,531],{"class":151},[142,1841,276],{"class":197},[142,1843,1844],{"class":72,"line":501},[142,1845,650],{"class":197},[10,1847,1848,1849,850],{},"Mixing both in one sheet is normal: the logo floats and stays at the top, while product photos are embedded and follow their rows. For logo placement and\nscaling in detail, see ",[24,1850,1852],{"href":1851},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fadd-logo-image-to-excel-report-with-openpyxl\u002F","Add a Logo Image to an Excel Report with openpyxl",[128,1854,1856],{"id":1855},"common-pitfalls","Common pitfalls",[1858,1859,1860,1876],"table",{},[1861,1862,1863],"thead",{},[1864,1865,1866,1870,1873],"tr",{},[1867,1868,1869],"th",{},"Symptom",[1867,1871,1872],{},"Cause",[1867,1874,1875],{},"Fix",[1877,1878,1879,1894,1910,1921,1934,1945],"tbody",{},[1864,1880,1881,1885,1888],{},[1882,1883,1884],"td",{},"Tiny thumbnails",[1882,1886,1887],{},"Default row height",[1882,1889,1890,1893],{},[19,1891,1892],{},"set_row"," to 50–80 points before embedding",[1864,1895,1896,1901,1904],{},[1882,1897,1898,1900],{},[19,1899,173],{}," instead of pictures",[1882,1902,1903],{},"Reader's Excel does not support pictures in cells",[1882,1905,1906,1907,1909],{},"Use ",[19,1908,1667],{},", or require Microsoft 365",[1864,1911,1912,1915,1918],{},[1882,1913,1914],{},"Pictures disappear after a later step",[1882,1916,1917],{},"Workbook re-saved with openpyxl",[1882,1919,1920],{},"Do all processing before xlsxwriter closes the file",[1864,1922,1923,1926,1929],{},[1882,1924,1925],{},"Photos mismatched after sorting",[1882,1927,1928],{},"Images were floating, not embedded",[1882,1930,1906,1931,1933],{},[19,1932,169],{}," for row-bound pictures",[1864,1935,1936,1939,1942],{},[1882,1937,1938],{},"File much larger than expected",[1882,1940,1941],{},"Full-resolution photos",[1882,1943,1944],{},"Resize images to display size before embedding",[1864,1946,1947,1952,1955],{},[1882,1948,1949],{},[19,1950,1951],{},"AttributeError: embed_image",[1882,1953,1954],{},"Old xlsxwriter release",[1882,1956,1957],{},"Upgrade xlsxwriter",[128,1959,1961],{"id":1960},"performance-and-scale-notes","Performance and scale notes",[10,1963,1964],{},"File size is driven by the images themselves. A 4,000-pixel product photo displayed in a 90-pixel cell carries the full resolution into the workbook, so\ndownscale to roughly twice the display size with Pillow first. Identical images are stored once, which keeps repeated icons cheap. Large catalogues with\nhundreds of distinct photos are still slow to open in Excel regardless of how they were written, so consider linking to a photo per row instead of embedding\nevery image when the list runs into the thousands.",[128,1966,1968],{"id":1967},"conclusion","Conclusion",[10,1970,1906,1971,1973,1974,1976,1977,1979,1980,1982],{},[19,1972,169],{}," whenever a picture belongs to a row — product photos, status icons, per-row thumbnails — so it sorts, filters and copies with its data. Size\nrows and columns first, feed images from ",[19,1975,1042],{}," when they come from a database or API, add descriptions for accessibility, and downscale large photos. Keep\n",[19,1978,1667],{}," for logos and page furniture, and remember the compatibility rules: older Excel shows ",[19,1981,173],{},", pandas reads nothing, and openpyxl must never\nre-save a workbook that contains embedded pictures.",[128,1984,1986],{"id":1985},"frequently-asked-questions","Frequently asked questions",[10,1988,1989,1992],{},[1455,1990,1991],{},"Can openpyxl embed images inside cells?","\nNo. openpyxl adds floating images only, and it drops pictures in cells when it re-saves a workbook that contains them. Use xlsxwriter for embedded images.",[10,1994,1995,1998],{},[1455,1996,1997],{},"Does the image resize when I change the row height in Excel?","\nYes. An embedded picture is fitted to its cell, so making the row taller or the column wider enlarges it, keeping its aspect ratio.",[10,2000,2001,2004],{},[1455,2002,2003],{},"Can I embed the same image in thousands of cells?","\nYes. xlsxwriter stores each distinct image once and references it from every cell, so repeated icons add very little to the file size.",[10,2006,2007,2010],{},[1455,2008,2009],{},"What image formats are supported?","\nPNG and JPEG are the safe choices for embedded pictures. Convert other formats with Pillow before embedding.",[128,2012,2014],{"id":2013},"related","Related",[1449,2016,2017,2023,2030,2037,2044],{},[1452,2018,2019,2020,2022],{},"Up one level: ",[24,2021,27],{"href":26}," — every way to put pictures into a workbook.",[1452,2024,2025,2029],{},[24,2026,2028],{"href":2027},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fresize-and-position-images-in-excel-with-openpyxl\u002F","Resize and Position Images in Excel with openpyxl"," — anchoring floating images precisely.",[1452,2031,2032,2036],{},[24,2033,2035],{"href":2034},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fextract-images-from-an-excel-file-with-python\u002F","Extract Images from an Excel File with Python"," — getting pictures back out, including embedded ones.",[1452,2038,2039,2043],{},[24,2040,2042],{"href":2041},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002F","Building Excel Reports with XlsxWriter"," — the library behind embed_image.",[1452,2045,2046,2050],{},[24,2047,2049],{"href":2048},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fwrite-a-formatted-excel-report-with-xlsxwriter\u002F","Write a Formatted Excel Report with xlsxwriter"," — formats and layout around the pictures.",[2052,2053,2054],"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 .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}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 .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}",{"title":138,"searchDepth":201,"depth":201,"links":2056},[2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068],{"id":130,"depth":201,"text":131},{"id":338,"depth":201,"text":339},{"id":660,"depth":201,"text":661},{"id":1035,"depth":201,"text":1036},{"id":1320,"depth":201,"text":1321},{"id":1443,"depth":201,"text":1444},{"id":1660,"depth":201,"text":1661},{"id":1855,"depth":201,"text":1856},{"id":1960,"depth":201,"text":1961},{"id":1967,"depth":201,"text":1968},{"id":1985,"depth":201,"text":1986},{"id":2013,"depth":201,"text":2014},"2026-09-17","Put a product photo or status icon inside a cell rather than floating over the grid, so it sorts, filters and resizes with its row. Use xlsxwriter's embed_image, and know how it differs from insert_image.","md",[2073,2075,2077,2079],{"q":1991,"a":2074},"No. openpyxl adds floating images only, and it drops pictures in cells when it re-saves a workbook that contains them. Use xlsxwriter for embedded images.",{"q":1997,"a":2076},"Yes. An embedded picture is fitted to its cell, so making the row taller or the column wider enlarges it, keeping its aspect ratio.",{"q":2003,"a":2078},"Yes. xlsxwriter stores each distinct image once and references it from every cell, so repeated icons add very little to the file size.",{"q":2009,"a":2080},"PNG and JPEG are the safe choices for embedded pictures. Convert other formats with Pillow before embedding.","embed images inside cells with xlsxwriter",null,{"breadcrumb":2084},[2085,2087,2090],{"name":2086,"item":711},"Home",{"name":2088,"item":2089},"Formatting and Charting Excel Reports with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002F",{"name":27,"item":26},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-images-inside-cells-with-xlsxwriter",{"title":2093,"description":2094},"Embed Images Inside Excel Cells with xlsxwriter embed_image","Embed pictures in Excel cells from Python with xlsxwriter embed_image: sizing rows and columns, images from bytes, hyperlinks, compatibility with older Excel, and floating insert_image alternatives.","embed-images-inside-cells-with-xlsxwriter","formatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-images-inside-cells-with-xlsxwriter\u002Findex",[2098,2099],"charts-and-images","xlsxwriter","how-to","Nf9vRHRRGsAGZFHRUrpBggGdyOaJ6gfmEmb4gDdyMDM",[2103,2106],{"title":1317,"path":2104,"stem":2105,"children":-1},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-a-matplotlib-chart-in-an-excel-report","formatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fembed-a-matplotlib-chart-in-an-excel-report\u002Findex",{"title":2107,"path":2108,"stem":2109,"children":-1},"Export an Excel Chart as an Image with Python","\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fexport-an-excel-chart-as-an-image","formatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel\u002Fexport-an-excel-chart-as-an-image\u002Findex",[2111,2113],{"path":2112,"title":2088},"\u002Fformatting-and-charting-excel-reports-with-python",{"path":2114,"title":27},"\u002Fformatting-and-charting-excel-reports-with-python\u002Finserting-images-and-logos-into-excel",[],[2117,2120,2123,2126,2129,2132],{"path":2118,"title":2119,"kind":2100},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fbuild-a-dashboard-sheet-with-charts-from-multiple-tabs","Build a Dashboard Sheet with Charts from Multiple Tabs",{"path":2121,"title":2122,"kind":2100},"\u002Fautomating-reporting-workflows\u002Fbuilding-multi-sheet-excel-dashboards\u002Fbuild-a-rolling-12-month-chart-on-an-excel-dashboard","Build a Rolling 12-Month Chart on an Excel Dashboard",{"path":2124,"title":2125,"kind":2100},"\u002Fautomating-reporting-workflows\u002Fgenerating-excel-reports-from-templates\u002Fkeep-charts-and-images-when-filling-an-excel-template","Keep Charts and Images When Filling an Excel Template",{"path":2127,"title":2128,"kind":2100},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-a-chart-to-an-excel-file-with-xlsxwriter","Add a Chart to an Excel File with xlsxwriter",{"path":2130,"title":2131,"kind":2100},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fadd-sparklines-to-an-excel-report-with-xlsxwriter","Add Sparklines to an Excel Report with xlsxwriter",{"path":2133,"title":2134,"kind":2100},"\u002Fformatting-and-charting-excel-reports-with-python\u002Fbuilding-excel-reports-with-xlsxwriter\u002Fbuild-a-waterfall-chart-in-excel-with-python","Build a Waterfall Chart in Excel with Python",1790972116687]