Проблема: Не отображается кнопка экспорт в Excel у одного из пользователей. Системные настройки в порядке, у других пользователей все отображается. Попытка залогиниться тем же пользователем с другого компьютера - кнопка на месте.

Таким образом, выяснили, что проблема в компьютере. Система стоит давно, прежде проблем не наблюдалось. В системе установлен MS Office 2010

Решение: Решается через изменение конфигурации. При отрисовке кнопки система проверяет, установлен ли на компьютере Excel. В старых версиях Terrasoft в конфигурации жесткая привязка к списку версий Excel, и нового офиса среди них нет.

Добавить его в конфигурацию:

1. Войти в TSAdmin.exe;
2. Найти поиском компонент scr_MSOfficeUtils и открыть его двойным кликом либо по Enter;
3. Внутри скрипта найти процедуру GetIsMSOfficeApplicationIstalledViaRegistry и в перечислении версий Excel занести полный список: SupportedMSOfficeVersionArray = new Array('14.0', '12.0', '11.0', '10.0', '9.0');
Сделать это нужно единоразово и работать будет для всех пользователей, которым позднее будет установлен MSOffice 2010. Загружать конфигурацию через TSAdmin.exe можно с любого компьютера.

Нравится

Поделиться

0 комментариев
Показать все комментарии

Вопрос такой: нужно автоматически выполнить экспорт после открытия формы отчета в FastReport. У меня не получается отловить событие по которому я могу это сделать, пробовал на событии OnShow базового окна отчета, но не получилось. Пока получился только вариант на OnClose, но это не красиво, т.к. пользователю надо нажимать кнопку закрытия окна отчета.
Как быть ?

Нравится

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

Отчет по выделенным записям или с использованием окна фильтрации?

По выделенной записи.

Решение "в лоб"
находим function ShowSelectedRecordsReport(...) в скрипте scr_ReportUtils
модифицируем ее примерно так

ReportPreviewer.Build(); // из оригинальной фунции
var frpMain = ReportPreviewer.ComponentsByName('frpMain');
frpMain.Report = Report;
if (frpMain.Report.Caption == 'Заголовок нужного отчета'){  // любой идентификатор нужного отчета
    frpMain.PrepareReport();
    frpMain.IsVisible = false;
    ReportPreviewerComponent.DatasetByUSI(FilteredDatasetCode) = ReportDataset;
    frpMain.PreviewReport();
    var TempFileName = System.CreateObject('TSObjectLibrary.Value');
    var FileNames = System.CreateObject('TSObjectLibrary.StringsList');
    if ((System.PromptForFileNames(FileNames, '*.rtf', '', "Выберите файл", ''))) {
	TempFileName.Value = ExtractFileNameWithoutExtension(FileNames.Text.substr(0, FileNames.Text.length-2)) + '.rtf';
	try {
    	   frpMain.Export(retRTF, TempFileName, false);
	} catch (e){
	} 	
     }	
     return;	
} else {
   ReportPreviewer.Prepare(); // из оригинальной функции
}

Без претензии на "красоту", основное - идея:smile: Творческая переработка и оптимизация рекомендуются.
Производится экспорт в rtf без показа отчета, в какой файл - выбираем в диалоговом окне.

Александр, спасибо. Идея как раз то что надо.
Я немного переработал ее для своих нужд, сделал в гриде документов отдельную кнопку для этой обработки, кроме того мне не нужно выбирать файл, надо просто сохранить во временный и после этого автоматически открыть его в MS Word, получилось так:

function btnRTFletterOnClick(Control) {
	//по кнопке сформировать файл формата RTF в соответствии с шаблоном FastReport
	var ReportCode = 'fr_ReportLetterPrintForm';
	var FilteredDatasetCode = 'ds_ReportLetterPrintForm';
	var Report = Services.GetNewItemByUSI(ReportCode);
	var ReportPreviewer = Services.GetNewItemByUSI('wnd_BaseFastReportPreview');
	var ReportPreviewerComponent = ReportPreviewer.Attributes('ReportPreviewer');
	var ReportDataset = Services.GetNewItemByUSI(FilteredDatasetCode);	
	SetAttribute(ReportPreviewer, 'Report', Report);
	ApplyDatasetFilter(ReportDataset, 'ID', dlData.Dataset.Values('ID'), true);		
	ReportPreviewer.Build();
 
	var frpMain = ReportPreviewer.ComponentsByName('frpMain');
	frpMain.Report = Report;
    frpMain.PrepareReport();
    frpMain.IsVisible = false;
    ReportPreviewerComponent.DatasetByUSI(FilteredDatasetCode) = ReportDataset;
    frpMain.PreviewReport();
 
    ScriptUtils.BeginProcessing(); //задержка для стабильного формирования RTF файла
	ScriptUtils.Sleep(100);	
	ScriptUtils.EndProcessing();
 
    var TempFileName = System.CreateObject('TSObjectLibrary.Value');
		try {
           	var FileNameStr = 'letter';
			var Extension = '.rtf';
			TempFileName.Value = GetTemporaryFileName(FileNameStr + Extension);
			frpMain.Export(retRTF, TempFileName, false);
			var WShell = System.CreateObject('WScript.Shell');
			var File = TempFileName.Value;
			WShell.Run('winword.exe ' + File, 1);
        	} 
			catch (e){
        			}      
}

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

"Тюрин Юрий" написал:В ходе отладки выявился один странный момент если непосредственно перед формированием временного файла вызывать отладчик, то все отлично, а если без него, то файл формируется пустым. Помогло введение в код небольшой задержки.

а вот это интересный момент:smile:

Показать все комментарии

Данное сообщение будет полезно всем, кто занимается экспортом в Excel, особенно при выгрузке больших объемов данных.

Сам принцип довольно прост - формируем двухмерный вариантный массив, указываем область в Excel, куда необходимо его разместить и выгружаем. Самой проблемной остается задача заполнения массива. Для выгрузки из Delphi есть множество примеров/ Привожу один из них:

Но как сделать то же самое, только на языке JavaScript в конфигурации Terrasoft CRM и какая при этом будет скорость?

Привожу пример кода:

function Main() {
      var Excel = new ActiveXObject('Excel.Application');
      var Workbook = Excel.Workbooks.Add();
      var Sheet = Workbook.Sheets.Add();
      var StartRowNumber = 1;
      var StartColNumber = 1;
      var RowsCount = 10000;
      var ColumnsCount = 200;
      var Range = GetRangeObject(RowsCount, ColumnsCount);
      for (var X = 1; X = RowsCount; X++) {
            for (var Y = 1; Y = ColumnsCount; Y++) {
                  Range.Value(X, Y) = X * Y;
            }
      }
      var TopLeftRangeValue = GetRangeValue(StartRowNumber, StartColNumber);
      var BottomRightRangeValue = GetRangeValue(StartRowNumber + RowsCount - 1,
            StartColNumber + ColumnsCount - 1);
      Log.Write(1, 'Начало вставки записей в диапазон "' + TopLeftRangeValue +
            ':' + BottomRightRangeValue + '" = ' + RowsCount * ColumnsCount);
      Sheet.Range(TopLeftRangeValue, BottomRightRangeValue) =
            Range.ValuesAsArray;
      Log.Write(1, 'Конец вставки записей');
      Excel.Visible = true;
}

Для запуска в скрипт необходимо включить скрипт scr_UserReportCommon в котором находятся функции GetRangeValue() и GetRangeObject().
Функцию GetRangeValue нужно заменить на новую:
function GetRangeValue(RowNumber, ColumnNumber) {
      if ((RowNumber 1) || (ColumnNumber 1)) {
          return false;
      }
      var MaxCharNumber = 26;
      if (ColumnNumber > MaxCharNumber) {
            var FloorValue = Math.floor((ColumnNumber - 1)/MaxCharNumber);
            var FirstChar = String.fromCharCode(64 + FloorValue);
            var ColumnNumber = ColumnNumber - FloorValue * MaxCharNumber;
      } else {
            var FirstChar = '';
      }
      var RangeColumn = FirstChar + String.fromCharCode(64 + ColumnNumber);
      return RangeColumn + RowNumber;
}

Принцип действия следующий:
1) Создаем массив необходимых размеров:
      var Range = GetRangeObject(RowsCount, ColumnsCount);

2) Заполняем массив данными:
      for (var X = 1; X = RowsCount; X++) {
            for (var Y = 1; Y = ColumnsCount; Y++) {
                  Range.Value(X, Y) = X * Y;
            }
      }

3) Определяем адрес левой верхней и правой нижней ячеек по номерам строки и колонки (например, получаем следующие значения "A1", "GR10000"):
      var TopLeftRangeValue = GetRangeValue(StartRowNumber, StartColNumber);
      var BottomRightRangeValue = GetRangeValue(StartRowNumber + RowsCount - 1,
            StartColNumber + ColumnsCount - 1);

4) И самое главное - запускаем вставку данных из массива:
      Sheet.Range(TopLeftRangeValue, BottomRightRangeValue) =
            Range.ValuesAsArray;

При запуске выводит в лог следующее сообщение:
[09.03.04 09.50.32.342] (W) Начало вставки записей в диапазон "A1:GR10000" = 2000000
[09.03.04 09.50.36.628] (W) Конец вставки записей

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

При выгрузке старайтесь, чтобы объем размер области совпадал с размером массива.
И не забывайте, что в Excel существуют ограничения на количество строк и колонок в листе - строк не более 65536, а колонок - не более 256.

Нравится

Поделиться

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

Не совсем так. В последней версии Excel колонок и строк может быть больше. Отсюда важный момент - при работе с очень большими файлами вариантный массив может не создасться, если создавать его по всей используемой области. Пишу просто потому что сам один раз на такое нарвался :)

Думаю, что при работе с большими объемами данных могут быть проблемы, которые, связаны с ограниченными ресурсами машины (например, памяти). В этом случае можно разделять массив данных на несколько более мелких блоков, каждый из которых необходимо будет вставлять в Excel отдельно.

Одним из быстрых способов также будет простой экспорт в csv формат

Интересно, а как можно организовать если на этапе создание объекта Range не известно количество строк?

И все же одним из быстрых способов будет простой экспорт в csv формат. Или же можно формировать результат непосредственно в формате Open XML для последних версий MS Office. Хотя с Open XML конечно сложнее.

Показать все комментарии

Здравствуйте, есть ли возможность на данный момент заменить экспорт в xls на экспорт в ods.
Дело в том, что в нашей компании мы не используем пакет MS Office. Террасофт в отсутствии Exel откаывается экспортировать в xls и приходится экспортировать отчеты в rtf и править их из OOo Writer, но это очень неудобно.

Спасибо.

Нравится

1 комментарий

Думаю, после выхода Office 14 можно будет сделать выгрузку в формат Office Open XML (который этим офисом будет поддерживаться) и убить двух зайцев сразу.
Ранее - ждём ответа специалистов Terrasoft...

Показать все комментарии

Добрый день. Каким образом можно убрать кнопку "Экспорт" с гридов вывода контрагентов и контактов? Оставить ее нужно только администраторам.

Спасибо.

Нравится

1 комментарий

Уберите галку в системном параметре GridCanExport

Показать все комментарии