JLink helps for your simple example.
I tested the code below on Windows and Linux. Seems to work just fine.
However, I doubt using JLink will work reasonably fast for really big data, maybe with parallelization.
Or you may want to resort to NETLink then.
Or use a Python solution and call this from Mathematica.
Needs["JLink`"];
checkType[val_Image]:=True;
checkType[val_?NumberQ]:=True;
checkType[val_String]:=True;
checkType[_]=False;
ExcelExport[xlsFile_String, data:{ {__?checkType}.. }, rowHeight_:40] :=
Module[{wb, sheet, writeCell},
JLinkJavaBlock[JLinkLoadJavaClass["org.apache.poi.xssf.usermodel.XSSFColor"];
wb = JLink`JavaNew["org.apache.poi.xssf.usermodel.XSSFWorkbook"];
sheet = If[wb@getNumberOfSheets[] > 0,
wb@getSheetAt[0]
,
wb@createSheet[$Version]
];
writeCell[noImg_?NumberQ, cell_, ___]:=cell @ setCellValue[noImg];
writeCell[str_String, cell_]:=cell @ setCellValue[str];
writeCell[img_Image, _, ri_Integer, ci_Integer]:= Block[{bytes, pictureId, drawing, myAnchor, myPicture},
bytes = Normal @ ExportByteArray[img, "PNG"];
pictureId = wb@addPicture[bytes, wb@PICTUREUTYPEUPNG];
drawing = sheet@createDrawingPatriarch[];
myAnchor = JLink`JavaNew["org.apache.poi.xssf.usermodel.XSSFClientAnchor"];
myAnchor@setCol1[ci-1];
myAnchor@setRow1[ri-1];
myPicture = drawing@createPicture[myAnchor, pictureId];
myPicture@resize[]
];
Do[
row[r] = sheet@createRow[r - 1];
row[r]@setHeightInPoints[rowHeight];
Do[
cell[r, c] = row[r]@createCell[c - 1];
writeCell[data[[r, c]], cell[r, c], r, c]
, {c, Dimensions[data][[2]]}
]
,
{r, Dimensions[data][[1]]}
];
foutstream = JLink`JavaNew["java.io.FileOutputStream", xlsFile];
wb@write[foutstream];
foutstream @ close[];
wb@close[];
];
xlsFile
];
sq = ImageResize[Image[GraphPlot[#,PlotStyle->{Black,Thick},Background->LightBlue],ImageResolution->200], {100}]&;
data={{1,sq@CompleteGraph[3],sq@CompleteGraph[4],sq@CompleteGraph[5]},
{2,sq@CompleteGraph[6],sq@CompleteGraph[7],sq@CompleteGraph[8]}};
test = ExcelExport["test.xlsx",data];
SystemOpen @ test

"XML","JSON"or"CSV"instead of a closed format from proprietary software? – rhermans Aug 07 '23 at 11:19{3, ExportString[CompleteGraph[3], {"Base64", "GXL"}], ExportString[CompleteGraph[3], {"Base64", "PNG"}]}. Also,"HTML"could be another Open Standard file format. – rhermans Aug 07 '23 at 14:33Export["file.csv", {3, ExportString[CompleteGraph[3], {"Base64", "GXL"}], ExportString[CompleteGraph[3], {"Base64", "PNG"}]}, "CSV"]Is this correct? It's not working for me. The ExportString function is returning a wall of text instead of images. One of the reasons I like Excel is that you can apply filters in any way you want (although not on images). – internet Aug 07 '23 at 15:09{1, data1, data2, data3, image}. Here,data1, data2, and data3hold the filtering data that users can employ. Depending on the conditions applied todata1, data2, and data3, the row might either be retained or removed, but the image will always be associated with the row. – internet Aug 07 '23 at 16:55