воскресенье, 25 марта 2012 г.

C#. Работа с гиперссылками в Excel через позднее привязывание

Работа с гиперссылками в Excel через позднее привязывание



При обращении к свойствами или методами любых объектов приложений MS Office необходимо увязать эти обращения с целевыми объектами. Существует два типа связывания: раннее и позднее. 
Раннее связывание позволяет осуществить ряд проверок на валидность типов параметров и сущностей вызываемых объектов, но не поддерживает совместимость в работе при вызове методов из разных версий документов MS Office.
Позднее привязывание сопоставляет вызовы свойств и методов соответствующим объектам уже в процессе выполнения программы. Данная схема применяется в системах, где используется несколько версий MS Office или поддерживаются разные архитектуры процессоров.



Столкнулся недавно с потребностью извлечения адресов гиперссылок, привязанных к ячейкам при работе с данными Excel документов.
Поиски готовых примеров, описаний или алгоритмов как это реализуется в интернете, ни к чему не привели. Поэтому предлагаю свою реализацию этого.

Код самой функции:


// Получить ссылку ячейки
public string GetLink(string AAddress)
{
try
{
FRange = FWorksheet.GetType().InvokeMember("Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); // Формируем Range для переданного AAddress

var HyperLinks = FRange.GetType().InvokeMember("Hyperlinks", System.Reflection.BindingFlags.GetProperty, null, FRange, null); // Получаем массив гиперссылок

if( HyperLinks != null )
{
var count =(int)HyperLinks.GetType().InvokeMember("Count", System.Reflection.BindingFlags.GetProperty, null, HyperLinks ,null); // Считаем ссылки

if( count > 0 )
{
var HyperLink = HyperLinks.GetType().InvokeMember("Item", System.Reflection.BindingFlags.GetProperty, null, HyperLinks , new object[]{1}); // Из массива ссылок берём первую
if(HyperLink != null )
{
return HyperLink .GetType().InvokeMember("Address", System.Reflection.BindingFlags.GetProperty, null, HyperLink , null).ToString(); // Возвращаем адрес гиперссылки
}
}
}
}
catch(Exception e)
{
Service.UI.ShowMessage( e.Message+"\r\nИсточник: " + e.Source.SafeToString() + "\r\nСтэк: " + e.StackTrace.SafeToString());
}
return null;
}


Код класса для работы с документом и пример вызова:


public static void Main(string[] args)
{
Excel doc = new Excel();

doc.Visible = true;
doc.OpenBook( @"C:\Имя_документа.xls" );
doc.OpenWorksheet(1);
string link = doc.GetLink("A1");
Service.UI.ShowMessage("Ссылка: "+link);
}
public class Excel : IDisposable
{
object FExcel = null;
object FWorkbooks, FWorkbook, FWorksheets, FWorksheet, FRange;

// Конструктор
public Excel()
{
FExcel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));
}

// Деструктор
public void Dispose()
{
FWorkbooks = null;
FWorkbook = null;
FWorksheets = null;
FWorksheet = null;
FRange = null;

System.Runtime.InteropServices.Marshal.ReleaseComObject(FExcel);
GC.GetTotalMemory(true);
}

// Видимость
public bool Visible
{
get
{
return Convert.ToBoolean(FExcel.GetType().InvokeMember(
"Visible", System.Reflection.BindingFlags.GetProperty, null, FExcel, null));
}

set
{
FExcel.GetType().InvokeMember(
"Visible", System.Reflection.BindingFlags.SetProperty, null, FExcel, new object[] { value });
}
}

// Открыть книгу
public void OpenBook(string AFilePath)
{
FWorkbooks = FExcel.GetType().InvokeMember(
"Workbooks", System.Reflection.BindingFlags.GetProperty, null, FExcel, null);

FWorkbook = FWorkbooks.GetType().InvokeMember(
"Open", System.Reflection.BindingFlags.InvokeMethod, null, FWorkbooks, new object[] { AFilePath, true });

FWorksheets = FWorkbook.GetType().InvokeMember(
"Worksheets", System.Reflection.BindingFlags.GetProperty, null, FWorkbook, null);

FWorksheet = FWorksheets.GetType().InvokeMember(
"Item", System.Reflection.BindingFlags.GetProperty, null, FWorksheets, new object[] { 1 });
}

// Выбрать страницу
public void OpenWorksheet(int AIndex)
{
FWorksheet = FWorksheets.GetType().InvokeMember(
"Item", System.Reflection.BindingFlags.GetProperty, null, FWorksheets, new object[] { AIndex });
}

// Закрыть книгу
public void CloseBook()
{
FWorkbook.GetType().InvokeMember(
"Close", System.Reflection.BindingFlags.InvokeMethod, null, FWorkbook, new object[] { false });
}

// Закрыть приложение
public void Quit()
{
FExcel.GetType().InvokeMember(
"Quit", System.Reflection.BindingFlags.InvokeMethod, null, FExcel, null );
}

// Количество строк
public int RowsCount()
{
FRange = FWorksheet.GetType().InvokeMember(
"UsedRange", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, null );
if ( FRange == null )
return 0;
object Rows = FRange.GetType().InvokeMember(
"Rows", System.Reflection.BindingFlags.GetProperty, null, FRange, null );
if ( Rows == null )
return 0;
int Count = (int)Rows.GetType().InvokeMember(
"Count", System.Reflection.BindingFlags.GetProperty, null, Rows, null );
Rows = null;
return Count;
}

// Получить значение с ячейки
public string GetValue(string AAddress)
{
try
{
FRange = FWorksheet.GetType().InvokeMember(
"Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress });

return FRange.GetType().InvokeMember(
"Value", System.Reflection.BindingFlags.GetProperty, null, FRange, null).ToString();
}
catch
{
}
return null;
}
// Получить ссылку ячейки
public string GetLink(string AAddress)
{
try
{
FRange = FWorksheet.GetType().InvokeMember("Range", System.Reflection.BindingFlags.GetProperty, null, FWorksheet, new object[] { AAddress }); // Формируем Range для переданного AAddress

var HyperLinks = FRange.GetType().InvokeMember("Hyperlinks", System.Reflection.BindingFlags.GetProperty, null, FRange, null); // Получаем массив гиперссылок

if( HyperLinks != null )
{
var count =(int)HyperLinks.GetType().InvokeMember("Count", System.Reflection.BindingFlags.GetProperty, null, HyperLinks ,null); // Считаем ссылки

if( count > 0 )
{
var HyperLink = HyperLinks.GetType().InvokeMember("Item", System.Reflection.BindingFlags.GetProperty, null, HyperLinks , new object[]{1}); // Из массива ссылок берём первую
if(HyperLink != null )
{
return HyperLink .GetType().InvokeMember("Address", System.Reflection.BindingFlags.GetProperty, null, HyperLink , null).ToString(); // Возвращаем адрес гиперссылки
}
}
}
}
catch(Exception e)
{
Service.UI.ShowMessage( e.Message+"\r\nИсточник: " + e.Source.SafeToString() + "\r\nСтэк: " + e.StackTrace.SafeToString());
}
return null;
}
}


Хотя список функций работы с Excel объектами далеко не полный, код класса приведён для наглядности.

2 комментария:

  1. Как добавить гиперссылку в ячейку?

    ОтветитьУдалить
    Ответы
    1. Решение найдено здесь http://zecl.hatenablog.com/entry/20080129/p1
      xlsRange = xlsSheet.GetType().InvokeMember("Range", BindingFlags.GetProperty, null, xlsSheet, new object[] { "B1" });
      string b1 = (string)xlsRange.GetType().InvokeMember("Value", BindingFlags.GetProperty, null, xlsRange, null);
      xlHyperLinks = xlsSheet.GetType().InvokeMember("Hyperlinks", BindingFlags.GetProperty, null, xlsSheet, null);
      xlHyperlink = xlHyperLinks.GetType().InvokeMember("Add",BindingFlags.InvokeMethod,null,xlHyperLinks,new object[]{xlsRange,b1});

      Удалить