Java is a bit of pain when it comes to efficiency.
On Windows I would use NETLink (which is also painful because of lack of methods documentation).
The code below never needs more than half a GB of RAM (Kernel and FE) and
runs in less than half a minute.
Needs["NETLink`"];
InstallNET[];
LoadNETType["System.GC"];
bigExport[fileName_String, data_,chunk_:5000]:=NETBlock@Module[{xl,book,sheet,range,datachunk,writeSubMatrix},
writeSubMatrix[sh_,xl_,{{ri_,ci_},{rf_,cf_}}, subMat_?MatrixQ] :=
sh@Range[xl@Cells[ri,ci],xl@Cells[rf,cf]]@Value=subMat;
xl=CreateCOMObject["Excel.Application"];
book=xl@Workbooks@Add[];
sheet=book@Worksheets@Item[1];
Do[Print["writing rows ", row," to ",Min[row+chunk-1,Length@data]];
datachunk = Take[data, {row,Min[row+chunk-1,Length@data]}];
Print["datachunk Dimensions = ", datachunk//Dimensions];
writeSubMatrix[sheet,xl,{{row,1},{row-1,0}+Dimensions[datachunk]},datachunk],{row,1,Length[data],chunk}
];
book@SaveAs[fileName];book@Close[];xl@Quit[];
fileName
];
$outputFile=FileNameJoin[{NotebookDirectory[],"demo.xlsx"}];
Quiet@DeleteFile@$outputFile;
numRows=86370; numCols=28;
data = RandomReal[1, {numRows,numCols}];
bigExport[$outputFile,data] // AbsoluteTiming
(*SystemOpen @ $outputFile*)