SpreadsheetGear API alone won't solve your issue here. If your users have the ability to delete (or insert or rearrange) columns, and you have no way of knowing which columns were affected, given the worksheet scenario you provided above, you're simply out of luck.
To account for such operations, you would need to add some form of "metadata" in your worksheet columns that will let you track this. As you point out, if you have something like the following, where the [bracketed] row represents the Column Header...
[ A ] [ B ] [ C ] [ D ] [ E ] [ F ] [ G ]
1 2 3 4 5 6 7
...and a user deletes Columns D and E, you are left with the following:
[ A ] [ B ] [ C ] [ D ] [ E ] [ F ] [ G ]
1 2 3 6 7
To detect this you could introduce some known value somewhere in each column for which you can check for its existence, such as your own "header" row on Row 1 of the worksheet, such as:
[ A ] [ B ] [ C ] [ D ] [ E ] [ F ] [ G ]
Col A Col B Col C Col D Col E Col F Col G
1 2 3 4 5 6 7
If Columns D and E are deleted such as...
[ A ] [ B ] [ C ] [ D ] [ E ] [ F ] [ G ]
Col A Col B Col C Col F Col G
1 2 3 6 7
...then you'll presumably be able to detect as you loop over each column in this first row and compare it against your own list of known header names (i.e., "Col A", "Col B", etc.) and handle it accordingly. If your users can also insert columns or re-order columns, you may need to build more flexibility in this routine to handle such cases.
Instead of depending on the presence of some piece of information in a cell in each column, if you have the ability to give your customer a "template" file for which they can populate with data, a more robust solution could be to set each column to have a Defined Name associated with it. For instance, the below SpreadsheetGear code would give Columns A through D particular names:
using SpreadsheetGear;
...
IWorkbook workbook = Factory.GetWorkbook();
IWorksheet worksheet = workbook.Worksheets["Sheet1"];
worksheet.Names.Add("ProductColumn", "=$A:$A");
worksheet.Names.Add("PriceColumn", "=$B:$B");
worksheet.Names.Add("QuantityColumn", "=$C:$C");
worksheet.Names.Add("TotalColumn", "=$D:$D");
workbook.SaveAs(@"c:\path\to\workbook.xlsx", FileFormat.OpenXMLWorkbook);
// Give this workbook to your client to populate with data....
Then when you get the populated file back, to check for deleted columns you could do the following:
// Open populated workbook from customer. Columns could have been deleted, inserted or reordered...
IWorkbook workbook = Factory.GetWorkbook(@"c:\path\to\workbook.xlsx");
IWorksheet worksheet = workbook.Worksheets["Sheet1"];
// You'll need a list of known defined names for each column.
List<string> names = new List<string>() { "ProductColumn", "PriceColumn", "QuantityColumn", "TotalColumn" };
foreach (string name in names)
{
// The INames[...] indexer will return null if the name is not found.
IName definedName = worksheet.Names[name];
if (definedName == null)
{
Console.WriteLine($"They deleted column {name}!");
}
}
Bottom-line, you'll need to have some sort of identifying information within each column in the worksheet itself to detect such changes. If you have little to no control over the original workbook, you may just be out of luck to detect such changes.