OLE bstr не завершается нулем?

Итак, я пытаюсь автоматизировать Excel из C++ и OLE, используя функцию Autowrap, предоставленную Microsoft в их примерах автоматизации.

Я дошел до того, что могу прочитать строковое значение из ячейки в электронной таблице. Однако кажется, что для некоторых значений что-то не так со строкой, как будто она не завершается нулем. Вот мой код:

VARIANT result;
VariantInit(&result);
AutoWrap(DISPATCH_PROPERTYGET, &result, range, L"Value", 0);
wprintf(L"%s, len: %d\n", result.bstrVal, SysStringLen(result.bstrVal));
wprintf(L"abc %s\n", SysAllocString(L"def"));

Результат:

John Doe  á, 11
abc def

Принимая во внимание, что в файле Excel при отображении в Excel это выглядит так:

John Doe

(Может ли кодовая страница документа Excel каким-то образом быть проблемой? Это файл xlsx.)


person Prof. Falken    schedule 06.10.2015    source источник
comment
Можешь попробовать это с L"Value2"?   -  person Amit    schedule 06.10.2015
comment
@Амит, точно такой же результат!   -  person Prof. Falken    schedule 06.10.2015
comment
1. Это происходит с любой ячейкой/значением? 2 Что вы получаете с SysStringLen(results.bstrVal)? 3. Что вы получите, если попробуете wprintf(L"abc %s\n", SysAllocString(L"def"));?   -  person Amit    schedule 06.10.2015
comment
@Amit, обновленный вопрос. 1 - нет, бывает не всегда, только для некоторых значений.   -  person Prof. Falken    schedule 06.10.2015
comment
и функция LEN() внутри excel показывает 8, я полагаю?   -  person Amit    schedule 06.10.2015
comment
@ Амит, на самом деле 11! Итак, я предполагаю, что данные в ячейке как-то грязные...?!   -  person Prof. Falken    schedule 06.10.2015
comment
Я так думаю... может Excel скрывает лишние символы   -  person Amit    schedule 06.10.2015
comment
Я вставил значение ячейки в текстовый файл, а затем просмотрел его с помощью шестнадцатеричной программы просмотра Double Commanders. Последний символ — неразрывный пробел. (шестнадцатеричный A0). Так что все это время было виновником... @Amit   -  person Prof. Falken    schedule 06.10.2015
comment
@Amit, поэтому я думаю, что консоль не может отображать неразрывный пробел.   -  person Prof. Falken    schedule 06.10.2015


Ответы (1)


Джон Доу, 11 лет

Код довольно глючный и нуждается в исправлении. Переменная result не может быть IDispatch, она должна быть VARIANT. Вы слепо предполагаете, что свойство Range.Cell.Value возвращает строку, но это не то, как работает Excel. Требуется вызов VariantChangeType() для принудительного преобразования в VT_BSTR.

В противном случае символ á является простой проблемой кодирования текста. Доллары за пончики, вы скопировали строку из окна консоли. Который по умолчанию использует кодовую страницу 437 в Западной Европе и Америке. Код символа для á в этой кодовой странице — 0xA0. Это на самом деле U+00A0, неразрывный пробел. в Unicode, обычная кодовая точка в современном тексте.

Для того, чтобы он фактически отображался как пробел в приложении в режиме консоли, необходимо вызвать SetConsoleOutputCP(), чтобы переключить его на CP_UTF8, и изменить шрифт консоли с терминала на шрифт TrueType, такой как Consolas. Хорошо освещены в других вопросах и ответах на этом сайте.

person Hans Passant    schedule 06.10.2015
comment
Спасибо. Мне не нужно будет отображать его на самом деле, но я учту правильную обработку строк Unicode в своей программе и, прежде всего, исправлю ошибку VARIANT. - person Prof. Falken; 06.10.2015
comment
Хм, я неправильно вставил код. result всегда был VARIANT. Но вызов преобразования строки, необходимый для обеспечения строкового типа, о котором я понятия не имел. - person Prof. Falken; 08.10.2015
comment
Может быть, вы можете помочь мне с stackoverflow.com/questions/33149605/ тоже? - person Prof. Falken; 15.10.2015