Заказы на доработку 1С (сервис удаленной работы)

Хранилище

База знаний
Неназначенных незавершенных заказов: 2
Бесплатные отчеты, обработки, конфигурации, внешние компоненты для 1С Статьи, описание работы, методики по работе с 1С

Здравствуйте, гость ( Вход | Зарегистрироваться )



> Выборка данных из БД 1С          
xunicorn Подменю пользователя
сообщение 23.07.12, 18:12
Сообщение #1

Молчаливый
*
Группа: Пользователи
Сообщений: 4
Спасибо сказали: 0 раз
Рейтинг: 0

Здрасте. Может вопрос и заюзаный, но он есть: как сделать выборку данных из БД.

Я пишу приложение Win32 и мне нужны данные из 1С(например контрагенты). Насколько я понял есть несколько способов выборки, но я реально понял только 2:
1. Делать запрос к БД - но в MSSQL базы сохранены с произвольным именем, тут и проблемы;
2. Сделать экспорт БД у файл и розпарсить файл.

Первый способ отпадает потому, что не факт, что после обновления имя базы не поменяеться.
Второй способ плох потому, что явно нужно заходить в 1С и выбирать экспорт у файл.
Может есть третий способ, при котором не нужно заходить непосредственно в программу для экспорта и выбирать файл с данными(может есть статический файл данных для прописки пути в коде программы)

1С Предприятие 7.7(сетевая версия)
Конфигурация: "FORT:2000" редакция 3.77 от 23.01.2007

Ardi Подменю пользователя
сообщение 23.07.12, 18:30
Сообщение #2

Живет на форуме
***********
Гений телепатии и социального моделирования
Группа: Пользователи
Сообщений: 4121
Из: Киев
Спасибо сказали: 957 раз
Рейтинг: 0

Можно подключаться непосредственно к 1с и общаться с ней.

Цитата
Делать запрос к БД - но в MSSQL базы сохранены с произвольным именем

Лолшто?

1986?


Signature
Услуги 1С программиста 8.2, 7.7 (Плохо, дорого, очередь). Киев.

Vofka Подменю пользователя
сообщение 23.07.12, 19:53
Сообщение #3

У нас здесь своя атмосфера...
***********
Группа: Основатель
Сообщений: 13955
Из: Киев
Спасибо сказали: 4520 раз
Рейтинг: 3642.8

xunicorn, на чем пишете?

Сообщение отредактировал Vofka - 23.07.12, 20:00

xunicorn Подменю пользователя
сообщение 23.07.12, 22:25
Сообщение #4

Молчаливый
*
Группа: Пользователи
Сообщений: 4
Спасибо сказали: 0 раз
Рейтинг: 0

Цитата(Ardi @ 23.07.12, 19:30) *
Цитата
Делать запрос к БД - но в MSSQL базы сохранены с произвольным именем

Лолшто?

1986?


ну, насколько я понял сегодня из прочитаного это то, что 1С работает с БД коряво: ни нормальных имен таблиц, ни целосности данных(это мое мнение, которое я составил из прочитаного мною)

Цитата
xunicorn, на чем пишете?


C++ WinApi

Цитата
Можно подключаться непосредственно к 1с и общаться с ней.

Я не знаю насколько глубоко smile.gif мне придеться общаться з 1С, но сейчас мне нужны конкретные данные: контрагенты и информация по каждому. Каким способом лучше всего организовать эту выборку?

Ardi Подменю пользователя
сообщение 23.07.12, 22:43
Сообщение #5

Живет на форуме
***********
Гений телепатии и социального моделирования
Группа: Пользователи
Сообщений: 4121
Из: Киев
Спасибо сказали: 957 раз
Рейтинг: 0

Самый лёгкий способ - на сервером компьютере автоматом периодически запускается 1с и автоматом выполняет обработку.
Обработка сохраняет нужные данные в файл; кладёт на фтп.
Потом 1с автоматом закрывается. Или не закрывается и остается открытой и переодически выполняет обработку.


Signature
Услуги 1С программиста 8.2, 7.7 (Плохо, дорого, очередь). Киев.

Спасибо сказали: xunicorn,

Стрелок Подменю пользователя
сообщение 24.07.12, 4:54
Сообщение #6

Говорящий
***
Группа: Пользователи
Сообщений: 96
Спасибо сказали: 8 раз
Рейтинг: 0

Цитата(xunicorn @ 23.07.12, 23:25) *
ну, насколько я понял сегодня из прочитаного это то, что 1С работает с БД коряво: ни нормальных имен таблиц, ни целосности данных(это мое мнение, которое я составил из прочитаного мною)



Ой как же вы ошибаетесь. Другой вопрос в том как вы собираетесь получать данные. Влоб читать таблицы у вас врядли получится.

Может глянете в сторону ОЛЕ ну или ODBC.

Кроме того в 1С есть файлик-описание таблиц в котором можно узнать не только название таблиц но и названия полей (со свойствами). Хотя гораздо проще конечно же автоматом стартовать 1С в пакетном режиме и затем получать нужные вам данные из внешних сформированных файлов.


Signature
Программист 1С - любимчик бухгалтеров

Спасибо сказали: xunicorn,

Vofka Подменю пользователя
сообщение 24.07.12, 8:25
Сообщение #7

У нас здесь своя атмосфера...
***********
Группа: Основатель
Сообщений: 13955
Из: Киев
Спасибо сказали: 4520 раз
Рейтинг: 3642.8

1С Предприятие предоставляем пользователям механизм OLE DB. Если Вам вдруг захотелось использовать какие либо данные из 1С Предприятия в вашей программе – вы можете воспользоваться этим механизмом. Совсем просто это делается в таких языках, как Visual Basic или Delphi. В них вся работа с OLE-интерфейсами замаскирована от программиста насколько возможно. Это, с одной стороны, очень удобно, но с другой стороны – у нас всегда есть возможность повысить производительность путём использования С++. Он от своих адептов ничего не маскирует, это позволяет кое где сэкономить лишний байт или миллисекунду, но превращает работу с OLE DB в ад. Дело в том, что 1С не предоставляет для своих пользователей библиотеки импорта (*.tlb), поэтому единственный способ работы (если не использовать какие либо обёртки) – это позднее связывание. В Сети полно информации, как работать с 1С Предприятием из Delphi или Visual Basic, но практически совсем нет примеров с Visual C++.

Наиболее разумным и удобным будет следующее решение: мы организуем всю необходимую работу с 1С в виде отдельной экспортируемой функции глобального модуля (я надеюсь, Вы уже научились открывать в 1С Глобальный модуль и добавлять в него экспортируемые функции). Мы будем вызывать нужную функцию глобального модуля, которая будет возвращать нужное значение. Для многих практических приложений этого вполне достаточно.

#include <objbase.h>
#include <comdef.h>

//для начала инициализируем COM
HRESULT hr = CoInitialize(NULL);
if(FAILED(hr))
{
  AfxMessageBox("Невозможно инициализировать COM!");
  return FALSE;
}

/*
Прежде всего, нам необходимо получить
ID сервера OLE Automation 1С Предприятия.
*/
CLSID   cls77;

/*
Используем универсальный ключ 1С Предприятия

Подробнее см. КЖК – если у Вас установлена единственная
версия 1С – то этого достаточно, если несколько разных,
то нужно загрузить нужный. Вот краткий список возможных значений:

V1CEnterprise.Application - версия независимый ключ;
V77.Application - версия зависимый ключ;
V77S.Application - версия зависимый ключ, SQL-версия;
V77L.Application - версия зависимый ключ, локальная-версия;
V77M.Application - версия зависимый ключ, сетевая-версия.
*/

hr = CLSIDFromProgID(L"V77.Application", &cls77);
if(FAILED(hr))
{
  AfxMessageBox("Переустановите 1С Предприятие!");
  CoUninitialize();
  return FALSE;
}

//основной интерфейс, за который мы будем "дёргать"
IDispatch *pv77;

/*
Создаём инстанцию 1С Предприятия.

CLSCTX_LOCAL_SERVER – это значит, что 1С Предприятие
будет запущено в виде отдельного процесса – по другому оно не умеет.
*/

hr = CoCreateInstance(cls77, NULL, CLSCTX_LOCAL_SERVER, IID_IDispatch, (void**)&pv77);

if(FAILED(hr)  ||  !pv77)
{
  AfxMessageBox("Невозможно инициализировать интерфейс 1С Предприятия");
  CoUninitialize();
  return FALSE;
}

/*
пока всё было понятно и очевидно, дальше начинаются сложности…
1С предоставляет для запуска приложения функцию Initialize.
Вызов этой функции выглядит в VB элементарно

V7.Initialize(V7.RMTrade,"D:\1C\ТипаБаза /N"+Пользователь ,"NO_SPLASH_SHOW");

- мы практически забываем, что же происходит внутри.
Но занимающиеся С++ люди хладнокровные, трудностей не боятся.
Во-первых: мы должны помнить, что аргументы необходимо заталкивать задом наперёд…
Во-вторых: мы должны помнить, что RMTrade - это доже IDispatch интерфейс.. и его сперва нужно получить.
*/

VARIANT       vRet;
DISPID dispIDRmTrade, dispIDInitialize;
DISPPARAMS args = {0, 0, 0, 0};
VARIANT vars[3];  // Параметры для вызова Initialize

//Мы получим IDispatch интерфейс от RMTrade сразу в vars[2]

BSTR rmTrade = L"RMTrade";

hr = pv77->GetIDsOfNames(IID_NULL, &rmTrade, 1, 0, &dispIDRmTrade);

if (FAILED(hr))
{
  AfxMessageBox("Невозможно получить ID от RMTrade");
  if (pv77)
    pv77->Release();
  CoUninitialize();
  return FALSE;
}

hr = pv77->Invoke(dispIDRmTrade, IID_NULL, 0, DISPATCH_PROPERTYGET, &args,
      &vars[2], NULL, NULL);

if (FAILED(hr))
{
  AfxMessageBox("Невозможно получить интерфейс от RMTrade");
  if (pv77)
    pv77->Release();
  CoUninitialize();
  return FALSE;
}

//нужно получить ID для Initialize(..);
BSTR init = L"Initialize";
hr = pv77->GetIDsOfNames(IID_NULL, &init, 1, 0, &dispIDInitialize);
if (FAILED(hr))
{
  AfxMessageBox ("Не удалось получить ID от Initialize")
  if (pv77)
    pv77->Release();
  CoUninitialize();
  return FALSE;
}

/*
а теперь – вызвать этот самый Initialize(..),
но сперва необходимо заполнить массив аргументов функции
*/

args.cArgs = 3;
args.rgvarg = vars;
vars[0] = _variant_t("NO_SPLASH_SHOW");
vars[1] = _variant_t("/D D:\1S /N Denis /P Denis ");

/*
vars[2] – у нас уже есть, мы его получили при запросе
интерфейса RMTrade в момент предыдущего Invoke
*/

hr = pv77->Invoke(dispIDInitialize, IID_NULL, 0, DISPATCH_PROPERTYGET, &args,
   &vRet, NULL, NULL);

if(FAILED(hr) ||  (vRet.vt ==  VT_BOOL && vRet.bstrVal == 0x00))
{
  AfxMessageBox("Невозможно запустить 1С Предприятие");
}



надо заметить, что с этим последним Invoke нужно быть вообще осторожнее. У меня было такое, что даже при правильной командной строке вызов не удавался. При этом должно появиться окно, предлагающее задать имя базы, имя пользователя и т.п., возможно, это такая особенность дизайна 1С. В конце концов пришлось удалить старого пользователя, и создать нового. Осторожнее при разработке сервисов! Это окно будет появляеться на виртуальном десктопе, и Вы просто ничего не увидите (если конечно, не поставите галочку «взаимодействовать с рабочим столом»).

Есть несколько причин, по которым 1С может не быть запущен.
1) Вы пользуетесь локальной версией и в памяти уже висит какое то приложение с 1С Предприятием (в документации об этом сказано очень поверхностно – но поверьте на слово или сами поставьте эксперимент);

2) Произошла ошибка при компиляции глобального модуля (которая происходит каждый раз при запуске 1С), т.о. вам сначала желательно в конфигураторе поправить ошибки 1С Предприятия;

3) Произошло нарушение индексации таблиц из за некорректного завершения работы базы. Т.о. Вам сначала нужно запустить 1С Предприятие в монопольном режиме, что бы восстановить индексацию.
Кстати – в локальной версии тоже есть монопольный режим. Только вот зачем он нужен.. для меня загадка. Напомню, что командная строка для запуска в монопольном режиме должна заканчиваться /M.

теперь у нас есть запущенное приложение 1С Предприятия, можно к нему обращаться с помощью спецфункций: EvalExpr, CreateObject, ExecuteBatch, подробнее об этом – в официальном руководстве.

Экспортируемая функция глобального модуля, которую мы будем вызывать, будет называться ПриветМир, на языке 1С она выглядит следующим образом:

Функция ПриветМир (Слово) Экспорт
  ВозврСтрока = "Привет мир: " + Слово + "  спасибо за весточку в красно-желтую темницу!";  
  Возврат ВозврСтрока;
КонецФункции


У нас есть несколько способов вызвать эту функцию.

Вариант 1. Выполнить её с помощью функции EvalExpr, которая предназначена исполнения выражений на языке 1С (ExecuteBatch – тоже вариант).

Вариант 2. Взять ID непосредственно функции ПриветМир и вызвать сразу её. В 1С Предприятии нет никакой чёрной магии – она насквозь пропитана технологией OLE, поэтому у каждой функции есть ID. Тут я не уверен насчёт SQL версии, но использовать приведённый здесь код можно и с этой версией тоже.

Приступим!

1 Вариант.

VARIANT vRetEvalExpr;
UINT nArgErrRetEvalExpr;
DISPPARAMS argsRetEvalExpr = {0, 0, 0, 0};
VARIANT varsRetEvalExpr [1];  

///.......///

argsRetEvalExpr.cArgs = 1;
argsRetEvalExpr.rgvarg = varsRetEvalExpr;

BSTR                bstrEvalExpr      = L"EvalExpr";
DISPID              dispIDEvalExpr;
hr = pv77->GetIDsOfNames(IID_NULL, &bstrEvalExpr, 1, 0, &dispIDEvalExpr);    

if (FAILED(hr))
{
  AfxMessageBox("Невозможно получить ID от EvalExpr");
  if (pv77)
    pv77->Release();
  CoUninitialize();      
}

varsRetEvalExpr [0] = _variant_t("ПриветМир(\"Весточка 1С Предприятию\")");

/*
После этого Invoke можете проверить переменную vRetEvalExpr,
в ней должна располагаться строка-ответ от 1С Предприятия.
*/
hr = pv77->Invoke(dispIDEvalExpr, IID_NULL, 0, DISPATCH_PROPERTYGET,
  &argsRetEvalExpr, &vRetEvalExpr, NULL, NULL);



Способ с EvalExpr плох.. Почему? Потому что если бы в строке «Весточка 1С Предприятию» затесалась хотя бы одна кавычка, вызов произвести не удалось бы. Это накладывает определённые ограничения на наши действия. Поэтому, для серьёзных целей такой метод не подходит, к тому же – он не самый оптимальный по производительности, потому что сначала вызывается функция EvalExpr, которая потом вызывает функцию ПриветМир. «Чем больше посредников, тем больше в вине воды» (Copyright кто то из древних), поэтому мы не будем пользоваться функцией EvalExpr, а будем вызвать функцию ПриветМир непосредственно.

BSTR bstrHelloWorld      = L"ПриветМир";
DISPID dispIDHelloWorld;
hr = pv77->GetIDsOfNames(IID_NULL, &bstrHelloWorld, 1, 0, &dispIDHelloWorld);    

if (FAILED(hr))
{
  AfxMessageBox("Сначала добавьте в глобальный модуль фукнцию ПриветМир");
  if (pv77)
    pv77->Release();
  CoUninitialize();      
}

VARIANT vRetHelloWorld;
DISPPARAMS argsHelloWorld = {0, 0, 0, 0};
VARIANT varsHelloWorld[1];  

argsHelloWorld.cArgs = 1;
argsHelloWorld.rgvarg = varsHelloWorld;

varsK[0] = _variant_t("Привет в жёлто красную темницу");              

hr = pv77->Invoke(dispIDHelloWorld, IID_NULL, 0, DISPATCH_METHOD, &argsHelloWorld,
  &vRetHelloWorld, NULL, NULL);


Обратите внимание что при вызове Invoke используется DISPATCH_METHOD а не DISPATCH_PROPERTYGET.

[необходимо зарегистрироваться для просмотра ссылки]

pumbaE Подменю пользователя
сообщение 24.07.12, 14:16
Сообщение #8

Завсегдатай
Иконка группы
Группа: Местный
Сообщений: 113
Из: Запоріжжя
Спасибо сказали: 63 раз
Рейтинг: 0

Я за web сервис.
Конечно возникает проблема с обновлением при добавлении изменении реквизитов(но вроде у контрагентов давно ничего не менялось и в теории там нечему меняться) , но и с OLE тоже проблема с обновлениями никуда не девается.


Signature
Эт я почему раньше злой был? Потому, что у меня снегопата не было!

Vofka Подменю пользователя
сообщение 24.07.12, 14:19
Сообщение #9

У нас здесь своя атмосфера...
***********
Группа: Основатель
Сообщений: 13955
Из: Киев
Спасибо сказали: 4520 раз
Рейтинг: 3642.8

Цитата(pumbaE @ 24.07.12, 15:16) *
Я за web сервис.

В 7.7? 12201689.gif

Спасибо сказали: xunicorn,

pumbaE Подменю пользователя
сообщение 24.07.12, 14:26
Сообщение #10

Завсегдатай
Иконка группы
Группа: Местный
Сообщений: 113
Из: Запоріжжя
Спасибо сказали: 63 раз
Рейтинг: 0

Прошу прощения, осваиваю высокие технологии, так сказать 8.3 за вымя щупаю и не заметил такого маленького уточнения 7.7 , да еще и FORT да еще и 2007 года.


Signature
Эт я почему раньше злой был? Потому, что у меня снегопата не было!

xunicorn Подменю пользователя
сообщение 24.07.12, 15:22
Сообщение #11

Молчаливый
*
Группа: Пользователи
Сообщений: 4
Спасибо сказали: 0 раз
Рейтинг: 0

ок, спс за инфу, буду дальше копать

Не нашли ответа на свой вопрос?
Зарегистрируйтесь и задайте новый вопрос.


Ответить Новая тема
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 

RSS Текстовая версия Сейчас: 11.05.24, 13:41
1С Предприятие 8.3, 1С Предприятие 8.2, 1С Предприятие 8.1, 1С Предприятие 8.0, 1С Предприятие 7.7, Литература 1С, Общие вопросы по администрированию 1С, Методическая поддержка 1С - всё в одном месте: на Украинском 1С форуме!