По просьбе одного из участников публикую пример запроса для записи информации в текстовый файл.
Эта хранимая процедура сначала записывает во временную таблицу содержимое будущего XML файла, а затем пишет построчно это содержимое в файл. Файл дальше обрабатывается механизмом Epicor Service Connect.
Вы можете весь кусок, начиная с
exec('declare @RqNo nchar(10)
select @RqNo=PCR2001 from PCR2'+@CC+'00 (nolock)
и по
INSERT INTO #XMLCONTENT exec(@SQL)
выкинуть, а ниже создаваемый курсор
declare @LINETEXT nvarchar(max) declare text_lines cursor for select * from #XMLCONTENT (nolock)
заменить на свой 🙂
Ниже полный текст хранимой процедуры:
CREATE procedure [dbo].[usr_CopyRequisitionLines]
@CC nchar(2)='TR',--Код компании
@ReqNo nchar(10)='0000011990',--Номер требования
@CATALOG_NAME varchar(255)='D:\TEMP'--Название каталога
as
declare @bFolder int
DECLARE @FS int, @OLEResult int, @FileID int
DECLARE @hr int, @source varchar(30), @desc varchar (200)
declare @TEXT_FILE_NAME varchar(255)
DECLARE @PATH_AND_FILE varchar(255)
-- Зададим имя файла с расширением .xml
set @TEXT_FILE_NAME='CopyRequisitionLines.xml'
-- ОПРЕДЕЛИМ ИМЯ ФАЙЛА С КАТАЛОГОМ
set @CATALOG_NAME =
case
when len(@CATALOG_NAME)>0 and left(reverse(@CATALOG_NAME),1)<>'\' then @CATALOG_NAME+'\'
else @CATALOG_NAME
end
set @PATH_AND_FILE = @CATALOG_NAME + '\' + @TEXT_FILE_NAME
print @PATH_AND_FILE
-- CREATE FSO-OBJECT
EXEC @OLEResult = sys.sp_OACreate 'Scripting.FileSystemObject', @FS OUTPUT
IF @OLEResult <> 0 GOTO Error_Handler
--проверить - существует ли заданная директория, для этого вызовем функцию 'FolderExists'
--ранее созданного OLE объекта--------------------------------------------------------
execute @OLEResult = sp_OAMethod @FS,'FolderExists',@bFolder OUT, @CATALOG_NAME
IF @OLEResult <> 0 Or @bFolder = 0
BEGIN
--а если не существует - то создать её--------------------------------------------
execute @OLEResult = sp_OAMethod @FS,'CreateFolder',@bFolder OUT, @CATALOG_NAME
IF @OLEResult <> 0 And @bFolder = 0
BEGIN
GOTO Error_Handler
END
END
-- CREATE FILE-OBJECT
EXEC @OLEResult = sys.sp_OAMethod @FS,'CreateTextFile', @FileID OUTPUT, @PATH_AND_FILE, true, true
IF @OLEResult <> 0 GOTO Error_Handler
exec('declare @RqNo nchar(10)
select @RqNo=PCR2001 from PCR2'+@CC+'00 (nolock)
where PCR2001='''+@ReqNo+''' and PCR2037=''1''')
IF @@ROWCOUNT<>0
begin
create table #XMLCONTENT (
[LINETEXT] [nvarchar] (max) NOT NULL
)
declare @SQL nvarchar(max)
set @SQL='select ''<?xml version="1.0"?>
<msg:msg xsi:schemaLocation="http://Epicor.com/InternalMessage/1.1 http://scshost/schemas/Epicor/ScaInternalMsg.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:msg="http://Epicor.com/InternalMessage/1.1">
<msg:req tag="Requisition In">
<msg:dta>
<dta:Requisition xmlns:dta="http://www.scala.net/Requisition/1.1">
<dta:RqsnNum>''+convert(nchar(3),convert(int,isnull([MaxPrefix],''899''))+1)+substring(OLD.PCR1001,4,7)+''</dta:RqsnNum>
<dta:DeptCode>C''+replace(OLD.PCR1003,''C'','''')+''</dta:DeptCode>
<dta:WhCode>''+OLD.PCR1006+''</dta:WhCode>
<dta:RqsnType>''+OLD.PCR1007+''</dta:RqsnType>
<dta:InitiateApprovalProcess>1</dta:InitiateApprovalProcess>
<dta:RqsnLines>'' as Text
from PCR1'+@CC+'00 (nolock) OLD
LEFT JOIN (select max(left(PCR1001,3)) as MaxPrefix, substring(PCR1001,4,7) as Suffix from PCR1'+@CC+'00 (nolock) where left(PCR1001,1)=''9'' group by substring(PCR1001,4,7)) PRFX ON substring(PCR1001,4,7)=Suffix
where OLD.PCR1001='''+@ReqNo+'''
union all
select ''
<dta:RqsnLine>
<dta:LineNum>''+OLD.PCR2002+''</dta:LineNum>
<dta:StockCode>''+replace(replace(replace(OLD.PCR2007,char(185),''1''),''&'',''&''),''"'',''"'')+''</dta:StockCode>
<dta:StockDescr>''+replace(replace(replace(OLD.PCR2008,char(185),''1''),''&'',''&''),''"'',''"'')+''</dta:StockDescr>
<dta:StockDescr2>''+replace(replace(replace(OLD.PCR2024,char(185),''1''),''&'',''&''),''"'',''"'')+''</dta:StockDescr2>
<dta:QtyOrdered unitName="''+rtrim(SCUN003)+''">''+convert(nvarchar,OLD.PCR2009)+''</dta:QtyOrdered>
</dta:RqsnLine>'' as Text
from PCR2'+@CC+'00 (nolock) OLD
join SCUN'+@CC+'00 (nolock)
on SCUN001=OLD.PCR2020 and SCUN002=''*''
where OLD.PCR2001='''+@ReqNo+''' and OLD.PCR2037=''1''
union all
select ''
</dta:RqsnLines>
</dta:Requisition>
</msg:dta>
<msg:ctx>
<SrvLocation/>
<UserName>ServiceConnect</UserName>
<UserPwd>******</UserPwd>
<CompanyCode>'+@CC+'</CompanyCode>
<FiscalYear>2018</FiscalYear>
<AllowRaisingBusinessEvents>1</AllowRaisingBusinessEvents>
<Options>
<!-- RqsnTemplateMode: defines if incoming data is processed as requisitions or requisition templates
0 = requisition mode (default)
1 = requisition template mode -->
<RqsnTemplateMode>0</RqsnTemplateMode>
<!-- AllowRqsnAdd: defines if adding new requisitions (requisition templates) is allowed
1 = allowed (default)
0 = not allowed -->
<AllowRqsnAdd>1</AllowRqsnAdd>
<!-- AllowRqsnChange: defines if changing existent requisitions (requisition templates) is allowed
1 = allowed (default)
0 = not allowed -->
<AllowRqsnChange>1</AllowRqsnChange>
<!-- AllowRqsnDelete: defines if deleting existent requisitions (requisition templates) is allowed
1 = allowed (default)
0 = not allowed -->
<AllowRqsnDelete>1</AllowRqsnDelete>
</Options>
</msg:ctx>
</msg:req>
</msg:msg>'' as Text'
INSERT INTO #XMLCONTENT
exec(@SQL)
declare @LINETEXT nvarchar(max)
declare text_lines cursor
for
select *
from #XMLCONTENT (nolock)
open text_lines
FETCH NEXT FROM text_lines
INTO @LINETEXT
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC @OLEResult = sys.sp_OAMethod @FileID, 'Write', NULL, @LINETEXT
--print @str
FETCH NEXT FROM text_lines
INTO @LINETEXT
end
CLOSE text_lines
DEALLOCATE text_lines
select 'Lines are copied' as Text
end
else
begin
select 'No lines to copy' as Text
end
GOTO Done -- EXIT PROCEDURE
Error_Handler:
EXEC @hr = sys.sp_OAGetErrorInfo null, @source OUT, @desc OUT
SELECT hr = CONVERT (binary(4), @hr), source = @source, description = @desc
Done:
EXEC @OLEResult = sys.sp_OADestroy @FileID
EXEC @OLEResult = sys.sp_OADestroy @FS
RETURN @@error + @OLEResult
Не забудьте посмотреть заметку «SQL Server: OLE Automation Procedures», а также комментарии ниже списка опубликованных процедур.
Список опубликованных процедур:
- Как организовать рассылку напоминаний о просроченной задолженности?
- Как настроить Service Connect для автоматического импорта Заказов на Закупку из XLS файла?
- Как сделать многоуровневое утверждение заявок с помощью механизма отчётов MS SQL Server Reporting Services?
- Как создать и привязать к полю составной (иерархический) быстрый поиск (Composite Snap Search)?
- Как добавить шаблон документа для выходного канала MSRS?
- Имеется отчёт AFR для одной из компаний группы, он подходит для всех остальных компаний. Как его распространить?
- Как сделать отчёт с бюджетами для iScala по дням?
- Как сделать отчёт AFR в 2-х валютах с пересчётом по фиксированному курсу?
- How can I create an AFR report in 2 currencies using fixed rate?
- How to create AFR report with daily budgets from iScala?
- Как установить и каким образом можно использовать значение минимально допустимого остатка на складе?
- Как перенести отчёт MS SQL Server Reporting Services на другой сервер?
- Как получить, отредактировать и обновить отчёт MS SQL Server Reporting Services?
- Как сделать отчёт AFR в разных валютах с пересчётом по фиксированному курсу и выбором валюты?
- Как дать доступ к отчётам SQL Server Reporting Services?
- Как создать виртуальную машину для изучения MS SQL Server Reporting Services?
- Бэкап SQL 2008 R2 не восстановить на SQL 2008, что делать?
- Пример записи информации в txt файл из SQL запроса
- Как проконтролировать ввод новых, изменения и удаления существующих карточек покупателей, поставщиков, запасов?
- «Если это невозможно сделать, но очень хочется?» или «Как ввести примечание к строке требования?»
- Как разграничить доступ пользователей на сервере отчётов?
- How to delimit user access on the Reporting Server?
- Имеется шаблонная настройка для одной из компаний группы, она подходит для всех остальных компаний. Как её распространить?
- Выверяем данные между модулями УЗ и ГК
- Список проводок по запасам, для которых не созданы проводки ГК
- Проверяем отсутствие пропусков складских проводок и наличия других «вмешательств»
- Проводки истории Журнала Главной Книги модуля УЗ, имеющие иной период, чем в ГК
- Проводки ГК по счетам учёта запасов не из модуля УЗ
- Несоответствие истории проводок ГК модуля УЗ автоучёту
- Проводки ГК без соответствующих аналитических проводок
- How to add a document template for MSRS Output Channel
- Как зафиксировать заголовок отчёта на сервере отчётов (SSRS)?
- Многоуровневое утверждение заявок в Epicor iScala: как это работает? Доклад на конференции клиентов Эпикор в Москве 12.09.2017
- Multi Level Approvals for Requisitions: How it works?
- Как с помощью T-SQL прочитать список файлов в выбранной папке и отфильтровать нужные?
- Жизнь на Марсе есть! или Для модуля «Заработная плата» канал MSRS использовать можно, проверено!
- Электронные счета-фактуры как требования российского законодательства: доклад на конференции клиентов Эпикор 23.05.2013
- Как создать макрос в Excel и добавить его в меню надстроек?
- Как создать виртуальную машину VM Ware с ознакомительной версией Windows Server 2016 или Windows Server 2019?
- Как пользоваться сервером отчётности MS SQL Server Reporting Services (SSRS)?
- Как установить SQL Server Data Tools (SSDT) для Visual Studio 2019 и добавить проект Report Server?
- Что должно быть настроено в системе, чтобы при печати счетов-фактур в модуле «Заказы на Продажу» создавались XML файлы? / What should be configured in the system if we want XML files to be created when printing invoices in the Sales Orders module?
- Как автоматически загрузить курсы валют с сайта ЦБР?
- Как автоматически загрузить акт или УПД поставщика из системы ЭДО?
- Как совместить старую версию Scala/iScala с ЭДО?
- Как создать новый выходной канал для сохранения файла в папку EDI?
- Как проверить работоспособность рабочего потока Epicor Service Connect?
- Как установить и подключить готовый рабочий поток Epicor Service Connect?
- Как изменить настройки выходного канала для печати?
- Как организовать автоматическое создание проводок для массового списания основных средств?
- Как проверить соответствие исходящего сальдо предыдущего года и входящего сальдо текущего года?
- Как сделать вывод логотипа зависимым от кода компании?



Есть статья Фила Фактора (Phil Factor) «Чтение и запись файлов в SQL Server с использованием T-SQL» («Reading and Writing Files in SQL Server using T-SQL»). В статье как раз используется ‘Scripting.FileSystemObject’, как и в коде выше: для записи файлов процедура spWriteStringToFile, а для чтения ufsReadfileAsString.
Наконец-то дошли руки да и появилась реальная надобность это попробовать. С удивлением обнаружил, что приведенные автором (Phil Factor) функции не работают: у него, по всей видимости, collations не case sensitive, а у меня CS и поэтому у меня неряшливый стиль программирования, когда в одном месте указано @hr, а в другом — @HR, не проходит. В общем, публикую исправленный вариант:
и ещё:
Недавно столкнулся с интересной проблемой. Опишу все подробно и по порядку, может кому-то пригодится.
Итак, возникла задача, одновременно с распечаткой бумажной накладной создавать её электронную копию с записью в EDI папку.
Предложил использовать хранимую процедуру примерно следующего содержания:
Эта хранимая процедура сначала вызывает другую хранимую процедуру, которая заполняет требуемую таблицу данными.
Затем она вызывает вторую хранимую процедуру, которая записывает данные из этой таблицы в файловую систему.
Далее она выводит содержимое заполненной таблицы.
Хранимая процедура вызывается из кристалловского отчёта.
Когда проверяли этот отчёт всё работало.
Затем отчёт был добавлен в меню Скалы и… перестал работать. Точнее, файл перестал создаваться.
Стали разбираться. Я спросил, от имени какого пользователя работает Скала. Оказалось, что этот пользователь обладает расширенными правами, но не является db owner’ом. То есть, когда мы вызывали отчёт «напрямую» он обращался к SQL серверу от имени пользователя, его запустившего (с административными правами), а когда включили в меню Скалы, он стал вызываться от имени пользователя, через которого идёт обращение к SQL серверу со стороны Скалы. Я попросил подсоединиться к SQL серверу под этим пользователем и выполнить последовательно все 3 действия, описанных выше. Выяснилось, что всё работает, кроме хранимой процедуру, пишущей информацию в файловую структуру.
При попытке выполнить хранимую процедуру получили сообщения примерно такого содержания:
Стало всё понятно. Я предложил выполнить следующий запрос примерно такого содержания:
Хочу добавиль, что пользователь ScalaUser должен существовать в базе данных master. После выполнения запроса всё заработало 🙂
Попробовал воспользоваться функцией uftReadfileAsTable, опубликованной выше. Ругался разными словами 🙁
Не читался файл содержащий кириллические символы.
Никак не мог понять назначение трёх последних параметров в выражении
В заблуждение ввело то, что подобное выражение используется не только для чтения файла, но и для записи. Потом-таки разобрался:
1 означает ForReading (Открывает файл только для чтения),
false означает должен ли создаваться новый файл, если файл filename не существует (не должен. Именно наличие этого параметра и вводило в заблуждение, т.к. он требуется в случае открытия файла на запись, если он существует, или создания нового, если файла с таким именем нет, а мы собираемся только читать информацию из файла и в этом случае этот параметр не имеет смысла),
0 означает, что файл открывается как ASCII
А мне нужен был Unicode.
Заменил на -1 (-1 Открывает файл в кодировке Unicode, -2 Открывает файл, используя системную кодировку)
Наконец заработало 🙂
msdn.microsoft.com/en-us/library/aa265018(v=vs.60).aspx писал(а):
Description
Creates a specified file name and returns a TextStream object that can be used to read from or write to the file.
Syntax
object.CreateTextFile(filename[, overwrite[, unicode]])
The CreateTextFile method has these parts:
Part: object
Description: Required. Always the name of a FileSystemObject or Folder object.
Part: filename
Description: Required. String expression that identifies the file to create.
Part: overwrite
Description: Optional. Boolean value that indicates if an existing file can be overwritten. The value is True if the file can be overwritten; False if it can’t be overwritten. If omitted, existing files are not overwritten.
Part: unicode
Description: Optional. Boolean value that indicates whether the file is created as a Unicode or ASCII file. The value is True if the file is created as a Unicode file; False if it’s created as an ASCII file. If omitted, an ASCII file is assumed.
Таким образом,
предполагает, что будет создан файл только, если его не существует, в кодировке ASCII, а если нам нужно создать файл в формате Unicode, это нужно указать явно, например, таким образом:
Иногда полезно документировать подобные вещи хотя бы для себя, иначе приходится искать то, что уже когда-то было использовано, но забылось. Особенно при этом меня поражают вопросы на различных форумах: человек спрашивает, как создать файл в кодировке Unicode, ей, как водится, отвечают что-то типа "почитай документацию", человек потом пишет: "спасибо, разобралась" и всё. А рассказать другим… это, видимо, лишнее. 🙂