Возврат списков C # из веб-службы в Excel VBA - PullRequest
0 голосов
/ 21 сентября 2009

Это долго - извинения ....

Существует ли надежный способ возврата списков из C # в VBA через веб-сервис?

У меня есть веб-сервис, который возвращает «результат», который состоит из нескольких значений типа double, строк и т. Д. (Это инженерный расчет). Я также возвращаю список «Ошибки» и «Сообщения», которые содержат информацию о калькуляторе и дают вам некоторое представление о том, что, если что-то пошло не так. Так что эти списки потенциально пусты.

Вот мой класс C # 'NoteList', и оба типа 'Errors' и 'Messages' этого типа.

public class Note
{
    public int ID;
    public string Message;

    public Note()
    {
        ID = 0;
        Message = "";
    }

    public Note(int aID, string aMessage)
    {
        ID = aID;
        Message = aMessage;
    }
}

public class NoteList : List<Note>
{
}

Все довольно просто.

Мой класс 'Result' содержит два списка, таким образом:

public class Result
{
    // Lists
    public NoteList ErrorList = new NoteList();
    public NoteList MessageList = new NoteList();

    // Lots of other stuff...
}

Пока все хорошо ...

Я использовал VBA Web References Toolkit для создания некоторого прокси-сервера VBA «struct» для хранения результата. Сгенерированный код выглядит следующим образом ...

A struct_note:

Public ID As Long
Public Message As String

A struct_Result:

'"ErrorList" is an array with elements defined as struct_Note
'See Complex Types: Arrays in Microsoft Office 2003 Web Services Toolkit Help
'for details on implementing arrays.
Public ErrorList As Variant
'"MessageList" is an array with elements defined as struct_Note
'See Complex Types: Arrays in Microsoft Office 2003 Web Services Toolkit Help
'for details on implementing arrays.
Public MessageList As Variant

' plus the other stuff....

Я включил комментарии в приведенный выше список, сгенерированные инструментарием.

В моем VBA я создаю свой результат и использую его следующим образом:

Dim r as struct_Result
Dim ws As clsws_MyWebService ' This is another generated proxy class

и я наполняю это так:

Set r = ws.wsm_SomeMethod()

делать что-то, а потом «ничего», когда я закончу

Set r = nothing

Правильно - к моей проблеме ...

Я хочу запустить этот веб-метод несколько раз на листе Excel и отметить ошибки и сообщения, которые возвращаются. Так что я положил выше в цикле

for i = 1 to 10000
   Set r = ws.wsm_SomeMethod()
   ' do some analysis and write back to the spreadsheet
   Set r = nothing
next i

Это работает нормально, пока я не получу результат, в котором нет ошибок, т.е. ErrorList пуст. Я тогда получаю ошибку VB, говорящую

Screen shot of VB error
(источник: bigsmoke.com )

Я подозреваю, что VB создает что-то, что требует ErrorList с чем-то в нем, и жалуется, что массив имеет нулевой размер.

Кто-нибудь в стране стека overflow получил идеи о том, как решить эту проблему?

Спасибо

сал

-------- [РЕДАКТИРОВАТЬ] НИЖЕ ДОБАВЛЕНО ПОСЛЕ ОТВЕТА ОТ НИТЗМАХОНА -------------------

Я изменил свой код, чтобы разрешить пустой список следующим образом

public class Result
{
    // Lists
    [XmlElement(IsNullable = true)]
    public NoteList ErrorList = new NoteList();

    [XmlElement(IsNullable = true)]
    public NoteList MessageList = new NoteList();

    // Lots of other stuff...
}

Это изменяет WSDL так, как я не ожидал. До добавления атрибутов IsNullable WSDL, сгенерированный для «Результата», выглядел следующим образом:

  <s:complexType name="Result">
    <s:sequence>
      <s:element minOccurs="0" maxOccurs="1" name="ErrorList" type="tns:ArrayOfNote" />
      <s:element minOccurs="0" maxOccurs="1" name="MessageList" type="tns:ArrayOfNote"/>
      // Stuff deleted for clarity...
    </s:sequence>
  </s:complexType>
  <s:complexType name="ArrayOfNote">
    <s:sequence>
      <s:element minOccurs="0" maxOccurs="unbounded" name="Note" nillable="true" type="tns:Note" />
    </s:sequence>

У нас есть «Результат», содержащий «ArrayOfNote», содержащий обнуляемые «Заметки».

После добавления [XmlElement (IsNullable = true)] в списки я получаю этот WSDL:

  <s:complexType name="Result">
    <s:sequence>
      <s:element minOccurs="0" maxOccurs="unbounded" name="ErrorList" nillable="true" type="tns:Note" />
      <s:element minOccurs="0" maxOccurs="unbounded" name="MessageList" nillable="true" type="tns:Note" />
      // Stuff deleted for clarity...
    </s:sequence>
  </s:complexType>

Я потерял «ArrayOfNote», и у меня остался один (т.е. не массив) «ErrorList», который является «Note». Я запустил несколько примеров и даже добавил [XmlElement (IsNullable = true)] в списки, которые я получаю (в VB) одно значение, которое всегда является последним элементом списков C # на стороне сервера.

Должен ли я поместить [XmlElement (IsNullable = true)] куда-нибудь еще? Где ??

Спасибо!

Steve

Ответы [ 2 ]

1 голос
/ 22 сентября 2009

Код десериализатора XML, сгенерированный инструментом VBA Web Reference, очень буквально описывает порядок и формат XML, который он использует (на основе WSDL, из которого он был сгенерирован). Когда один из ваших списков в результирующем объекте пуст, сервер не генерирует для него элемент контейнера, а десериализатор VBA не готов обработать отсутствующий элемент. Попробуйте пометить оба списка в классе Result (на стороне службы) с помощью [XmlArray (IsNullable = true)] - это приведет к созданию пустого элемента контейнера с атрибутом xsi: nil, когда один (или оба) пуст, сохраняя десериализатор VBA доволен.

0 голосов
/ 21 сентября 2009

Ypu не может вернуть общий список. это специфично для .net. Я разработал множество веб-сервисов, используемых третьими сторонами, и мне всегда приходилось менять список на массив. Что легко сделать для использования другой языковой системой.

myList.ToArray ().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...