Работа с текстом в RTF из скрипта

Добрый день.
Уважаемое сообщество, помогите разобраться с такой задачей.

Terrasoft CRM 3.3.2
У нас в поле "Описание" таблицы контрагентов хранятся записи вида:

** горизонтальная линия **
Иванов Иван Иванович - 1 апреля 2010 г. 12:00:00
Клиент не оплатил счет

** горизонтальная линия **
Иванов Иван Иванович - 5 апреля 2010 г. 15:00:00
телефон клиента не отвечает

** горизонтальная линия **
Петров Петр Петрович - 12 апреля 2010 г. 14:15:25
клиент для нас потерян

, где ** горизонтальная линия ** - это нарисованная коричневая полоска, не текст.

Поступила задача реализовать удаление дублей таким образом, чтобы все "описания" дублей сливались в итогового контрагента с сортировкой по датам.

Я вижу такую последовательность действий: слить все описания во временный объект, в нем отсортировать и сохранить результат в "Описании" результирующего контрагента.

Из вышенаписанного вытекает нижеследующее:
1. Возможно ли из RTF-текста выдирать строки (желательно в виде текста, а не набора символов Unicode, в котором по-умолчанию хранятся кирилические символы) в какой-либо буферный объект?

2. Возможно ли проходом по RTF-тексту получить положение этой коричневой полоски, чтобы использовать ее как разделитель записей?

Есть ли какие возможности реализовать это?

Нравится

10 комментариев

Здравствуйте, Ерошенко Петр Семенович!

Алгоритм реализации данной задачи я вижу следующим:

1. Получить блок данных детали "Описание" и дату добавления этих данных;
2. Внести полученные на предыдущем шаге данные (в формате RTF), дату (в формате БД сервера), и контрагент в предварительно созданную таблицу с соответствующими полями (MESSAGE, MESSAGEDATE, ACCOUNT). При этом, необходимо преобразовать дату с формата RTF в тип данных "дата/время".
3. В созданной таблице отсортировать записи по messageDate, и вставить на деталь "Описание" (поле Description) все записи из колонки Message.

Вот пример кода который получает отдельные записи и дату их внесения:

function RTF()
{ 
	// Dataset = ds_Description
	var desc = 	Dataset.ValAsStr('Description');       
	getMessage(desc);	
        getMessageDate(desc);	
}
 
function getMessage(desc)
{    	
	var Message = "";
	var startIndex = 0;
	var endIndex = 0;
	// split into an array 
	var array = desc.split('\n');	
	for(var i = 0; i < array.length; i++)
	{
		if(array[i].indexOf("brdrs") != -1 && startIndex != 0)
		{
			 endIndex = i;
			 for(var a = startIndex; a < endIndex; a++)
			 {
			 	Message += array[a];
			 }   		
			 postToDB(Message);                        
			 // clear Message and Indexes
			 Message = "";
			 startIndex = 0;
			 endIndex = 0; 
		}
		if(array[i].indexOf("brdrs") != -1 && startIndex == 0)
		{
			startIndex = i;
		}
		// for last message
		if(array[i].indexOf("par}") != -1)
		{
			endIndex = i;
			for(var b = startIndex; b <= endIndex; b++)
			{
				Message += array[b];
			}
			postToDB(Message);                        
		}
	}
}
function getMessageDate(desc)
{   
	var messageDate = "";
	var array = desc.split('\n');
	for(var i = 0; i < array.length; i++)
	{
		if(array[i].indexOf("cs6") != -1)
		{
			for (var a = 0; a < array[i].length; a++)
			{
				if(array[i][a] == '-')
				{
					for(var b = a + 2; b < array[i].length; b++)
					{
						messageDate += array[i][b];
					} 
					postToDB(messageDate);					
					messageDate = "";
				}
			}
		}
	}
 
}
function postToDB(Message)
{
	//CODE FOR POSTING MESSAGE AND MESSAGEDATE TO DATABASE HERE
}

Спасибо за пример. А что дает поиск подстроки "cs6" в этом фрагменте? В моем случае она не встречается.

for(var i = 0; i < array.length; i++)
         {
                 if(array[i].indexOf("cs6") != -1)
                 {
                         for (var a = 0; a < array[i].length; a++)
                         {

Здравствуйте, Петр Семенович.

После символа "-" в RTF документе фиксируется дата создания сообщения. Однако данный символ может использоваться пользователем и в самом тексте сообщения. Поэтому, по определенным условиям необходимо идентифицировать строку, которая содержит в себе дату. В моем примере подстрока "cs6" предоставляет такую возможность:


\par \plain \cs6\f0\i\fs20\cf13 \u1045 \'c5\u1074 \'e2\u1075 \'e3\u1077 \'e5\u1085 \'ed\u1080 \'e8\u1081 \'e9\plain \f0\i\fs20\cf13 \plain \cs6\f0\i\fs20\cf13 \u1052 \'cc\u1080 \'e8\u1088 \'f0\u1085 \'ed\u1099 \'fb\u1081 \'e9\plain \f0\i\fs20\cf13 - 3 \plain \cs6\f0\i\fs20\cf13 \u1092 \'f4\u1077 \'e5\u1074 \'e2\u1088 \'f0\u1072 \'e0\u1083 \'eb\u1103 \'ff\plain \f0\i\fs20\cf13 2012 \plain \cs6\f0\i\fs20\cf13 \u1075 \'e3\plain \f0\i\fs20\cf13 . 12:51:12

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

Понятно, спасибо.

Возник еще один вопрос: возможно ли обновить поле "Description" итогового контрагента посредством UpdateQuery?

Здравствуйте Петр!

Обновить поле "Description" для контрагента, посредством UpdateQuery, возможно.
Для этого нужно создать updateQuery сервис, добавить значение Description типа "большой бинарный объект", параметр ID типа уникальный идентификатор, и фильтр сравнения tbl_Accaunt.ID = Parameter: ID.

После чего, запустите созданный сервис на исполнение.
К примеру:

var UpdateQuery = Services.GetNewItemByUsi('uq_AccountDesc');
var Parameters = UpdateQuery.Parameters;
var ID = Dataset.Values('ID');
var Desc = "new description";
SetParameterValue(Parameters, 'ID', ID);
SetParameterValue(Parameters, 'Description', Desc);
UpdateQuery.Execute();

"Олейник Дмитрий" написал:К примеру:

var UpdateQuery = Services.GetNewItemByUsi('uq_AccountDesc');
var Parameters = UpdateQuery.Parameters;
var ID = Dataset.Values('ID');
var Desc = "new description";
 SetParameterValue(Parameters, 'ID', ID);
 SetParameterValue(Parameters, 'Description', Desc);
 UpdateQuery.Execute();


А в там случае строку с RTF-текстом специально приводить к BLOB не нужно как здесь? Если запустить Ваш пример, то в базу запишется пустая строка.

В данном случае приводить строку к BLOB не нужно:

//Dataset = ds_description
var Dataset = DatasetLink1.Dataset;
Dataset.Open();
var DescNew = ' aaaa ';
Dataset.Edit();
Dataset.Values('Description') = DescNew;
Dataset.Post();
var Desc = Dataset.ValAsStr('Description');
MessageBox(Desc);

Дмитрий, попробовал запустить ваш пример в чистом виде

var UpdateQuery = Services.GetNewItemByUsi('uq_AccountDesc');
var Parameters = UpdateQuery.Parameters;
var ID = Dataset.Values('ID');
var Desc = "new description";
  SetParameterValue(Parameters, 'ID', ID);
  SetParameterValue(Parameters, 'Description', Desc);
  UpdateQuery.Execute();

При его выполнении не происходит записи RTF-текста в поле Description

exec sp_executesql N'UPDATE [dbo].[tbl_Account]
	SET [Description] = @P1,
	[ModifiedOn] = getdate(),
	[ModifiedByID] = ''{C727482F-D8EE-4416-B369-BDC9926E68F5}''
WHERE([tbl_Account].[ID] = @P2)',N'@P1 varbinary(8000),@P2 varchar(8000)',NULL,'{41229A2E-094E-4F28-B84E-316C94A6B522}'

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

Петр,
действительно если использовать updateQuery необходимо преобразовывать строку в BLOB.
Как вариант, предлагаю использовать способ описанный мной выше:

//dataset = ds_description
var Dataset = DatasetLink1.Dataset;
Dataset.Open();	
var DescNew = 'new value in RTF format ';
Dataset.Edit();
Dataset.Values('Description') = DescNew;
Dataset.Post();

В таком случае преобразование происходит автоматически:

exec sp_executesql N'UPDATE [dbo].[tbl_Account]
	SET [Description] = @P1,
	[ModifiedOn] = getdate(),
	[ModifiedByID] = ''{59B9825D-A16D-48AF-9C20-4DF1100E4BD5}''
WHERE([tbl_Account].[ID] = @P2)',N'@P1 varbinary(8000),@P2 uniqueidentifier',0x6E65772076616C756520696E2052544620666F726D617420,'E308B781-3C5B-4ECB-89EF-5C1ED4DA488E'
Показать все комментарии