In fact, the task is rather nontrivial, since You cannot directly retrieve the contents of an embedded object.
But you can come up with a workaround by copying the object to the clipboard. The data is copied to the buffer in some binary format, the description of which I could not find. However, it is not too complicated and can be disassembled. I'm not sure that the code will work absolutely always (I tested on Excel 2013), but at least it gives the direction of the solution:
[STAThread] static void Main(string[] args) { var app = new Microsoft.Office.Interop.Excel.Application(); app.Visible = false; var book = app.Workbooks.Open(@"d:\book.xlsx"); Worksheet sheet = book.Worksheets[1]; // перебираем все встроенные объекты OLEObjects objects = sheet.OLEObjects(); foreach (OLEObject obj in objects) { Clipboard.Clear(); obj.Copy(); // копируем встроенный объект в буфер обмена SaveObject(@"d:\tmp"); // сохраняем объект в каталог } book.Close(); app.Quit(); } static void SaveObject(string dirToSave) { // буфер обмена не содержит данные в нужном виде - выходим if (!Clipboard.ContainsData("Native")) { return; } // получаем данные из буфера в виде MemoryStream // стрим содержит некую бинарную структуру данных, включая строенный в объект файл using (var reader = new BinaryReader(Clipboard.GetData("Native") as MemoryStream)) { // сначала идут два байта с чем-то непонятным reader.ReadInt16(); // затем подряд имя встроенного файла // и полный путь к оригинальному файлу. // строки в стиле С (ограничены '\0') var fileName = ReadNullString(reader); var origFileName = ReadNullString(reader); // затем идут 8 байт непонятного назначения reader.ReadInt64(); // полное имя временного файла, куда будет выгружен файл, // если по ней дважды щелкнуть в окне Excel var tmpFileName = ReadNullString(reader); // затем идет размер файла var fileSize = reader.ReadInt32(); // сохраняем файл var saveTo = Path.Combine(dirToSave, fileName); using (var fs = new FileStream(saveTo, FileMode.Create)) { var block = new byte[4096]; int read = 0; do { int r = reader.Read(block, 0, 4096); fs.Write(block, 0, Math.Min(4096, fileSize - read)); read += r; } while (read < fileSize); } } } static string ReadNullString(BinaryReader reader) { var result = new StringBuilder(); byte tmp; while ((tmp = reader.ReadByte()) != 0) { result.Append((char)tmp); } return result.ToString(); }