Прежде чем я начну с проблемы, я хочу ее мотивировать. Моя задача - анализировать изменения в Excel-Sheet, но в отличие от записи изменений с помощью встроенного механизма, изменения должны обнаруживаться программно, и даже если пользователь отключил запись изменений или мой Excel-AddIn не установлен. Поэтому я использовал Microsoft.Interop. Библиотека Excel для доступа к листу и ячейкам внутри.
Теперь к проблеме: для поиска изменений, даже если пользователь отсортировал или переместил данные, я хотел иметь уникальный идентификатор для каждой ячейки, который прикрепляется к ней, даже если переместить или скопировать. Конечно, если скопировать, идентификатор будет дважды в листе, а новые добавленные ячейки не имеют идентификатора, но это нормально. Кроме того, этот идентификатор не должен быть виден пользователю, и пользователь не должен иметь возможность изменять или удалять его.
Итак, я поискал поле и нашел Range-Object , который может представлять собой одна ячейка и имеет разные элементы, к которым можно получить доступ. Одно специальное поле привлекло мое внимание, поле ID, которое выглядело как то, что я искал.
Guid guid = Guid.NewGuid();
((Range) worksheet.Cells[rowNr, columnNr]).ID = guid.ToString();
, а также читалось как
Guid guid = Guid.Parse(((Range) worksheet.Cells[rowNr, columnNr]).ID);
Это было идеально, потому что я мог хранить строку (в данном случае Guid как строка, например, 123463-fc34-c43a-a391-399fc2) и прочтите его. Он также прилип к ячейке и был перемещен, когда ячейка была перемещена и т. Д.
Но, к сожалению, это поле идентификатора не сохраняется, когда файл сохраняется, и я не знаю почему. Я имею в виду, что после закрытия и повторного открытия книги все идентификаторы исчезли.
Итак, мой вопрос в том, есть ли какой-либо другой член объекта Range, который может содержать строку (= Guid) и не виден пользователю. Я попробовал Name-Member и Comment-Member, но оба они видны пользователю и могут быть легко изменены.
Или есть способ сообщить Excel, что я тоже хочу сохранить поле ID , при сохранении листа?
Для тестирования вы можете создать проект, добавить ссылку на Microsoft.Office.Interop.Excel-Dll и добавить следующий код (в вашей системе должен быть установлен Excel). Это юнит-тест, Alex
Обновление 14.5.2011:
Поле «Имя» не является решением моей проблемы по следующим причинам:
Во-первых, и наиболее серьезным является тот факт, что кажется, что имя должно быть уникальный, но я хотел присвоить всем ячейкам подряд один и тот же идентификатор, что не работает.
Во-вторых, мне не совсем понятно, как получить доступ к полю имени в C #. Вы можете установить значение с помощью
((Range)worksheet.Cells[rowNr, columnNr]).Name = guid.ToString();
//Remark: Special dealing with guids required,
//if they start with a number or contain special characters.
, но это имеет серьезные проблемы. Если имя уже задано, генерируется исключение, если имя не задано, и вы пытаетесь получить к нему доступ с помощью
string name = ((Range)worksheet.Cells[rowNr, columnNr]).Name.Name;
, вы получаете исключение. И вам нужно Name.Name, потому что первое поле Name - это не строка, а целый объект имени, внутри которого есть другое поле имени, которое содержит строку.
И, наконец, если вы хотите проверить, не есть имя или нет, вы не можете сделать что-то вроде:
if(((Range)worksheet.Cells[rowNr, columnNr]).Name == null)
//Do something
, потому что он уже вызывает исключение при доступе к несуществующему полю имени.