Вопрос

Добрый день!
Подскажите, пожалуйста, почему не высчитывается сумма по столбцу?
В MasterData вывожу итоговую сумму столбца DetailData.
[SUM([ds_RD07_AP_ProjectManHour."EstimatedManHour"], DetailData2)]

У меня такой же вопрос

2 комментария

Оказалось, по какой-то причине, нельзя вывести итоги в МasterData. В Footer они вывелись.

Для корректного вычисления необходимо написать скрипт:
[SUM([<ds_RD07_AP_ProjectManHour."EstimatedManHour">], DetailData2)]

Ссылка на документацию Fast Report по агрегатным функциям: Aggregate functions

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

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

У меня такой же вопрос

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

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

Мне ожидать от Вас ответа на форуме или нужно обращаться к Вам на службу технической поддержки по email?

Наталия, специалист поддержки свяжется с Вами индивидуально. Дополнительно в этой теме продублирует решение.

Спасибо!

Наталия, добрый день.

Для решения вопроса 'Влияние курса валют на цену с налогом продукта' необходимо внести следующие изменения:

0. Перед внесением изменений настоятельно рекомендуем создать резервную копию БД.
1. Запустить приложение Terrasoft Administrator.
2. Открыт сервис scr_OfferingPriceEdit.
3. Найти функцию function UpdateBasicPrices(). Добавить в нее строку кода, как отображено на скриншоте:

OfferingPriceEdit.PrimaryPrice = 
                   RoundFloatValue(OfferingPriceObject.Price, 2);

http://i65.fastpic.ru/big/2014/1129/89/8e426a43b29f135894aeed360e27dc89.png

4. Найти функцию function UpdatePriceFieldDueDiscountChange(), заменить ее на:

function UpdatePriceFieldDueDiscountChange() {
         var Dataset = dlData.Dataset;       
/*      var Price = RoundFloatValue(CalcNonBasicPrice(OfferingPriceEdit.PrimaryBasicPrice * 
                   (100 - edtDiscountPercent.Value) / 100, OfferingPriceEdit.CurrencyID, 
                   OfferingPriceEdit.Rate), 2); */
 
    var Price = OfferingPriceEdit.PrimaryPrice - edtDiscount.Value; 
         Dataset.Attributes('DisableDiscountRecalc') = true;
         Dataset('Price') = Price;
         Dataset.Attributes('DisableDiscountRecalc') = false;
}

5. Сохранить внесенные изменения. Перезапустить приложение Terrasoft. Проверить работу функциональности.

Наталья, прошу сообщить по результату.

Допоможіть розібратись з перерахунком цін в рахунку при конвертації валюти
в файлі докладно описано

Разница в 2 копейки может набегать из-за округления, Вы указываете цену с налогом.

8,33 * 1,2 * 5 = 49,98

тоді щоб вірно рахувало суму потрібно не враховувати податок?

і що являє собою валюта базова?ми працюєм у гривнях але оприбуткування відбувається в іноемній валюті, як краще в даному випадку працювати з терасофтом

Видимо, вводить точную сумму без налога. Пусть с налогом само вычисляет.
О базовых валютах написана статья.

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

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

Для того, чтобы это сделать, следует создать колонку подзапроса:

111

Пример запроса:

SELECT
        "tbl_Invoice"."Amount" AS "Amount",
        "tbl_Invoice"."OwnerID" AS "OwnerID",
        (SELECT
                SUM("tbl_InvoiceSum"."Amount") AS "Amount"
        FROM
                "tbl_Invoice" AS "tbl_InvoiceSum"
        WHERE("tbl_InvoiceSum"."OwnerID" = "tbl_Invoice"."OwnerID")) AS "AmountSum"
FROM
        "tbl_Invoice" AS "tbl_Invoice"

Пример сервиса в приложении.

Поделиться

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

Собственно, подзапросы разные бывают. Чащё даже не сумму вытягивают, а максимальное значение или первое подходящее по критерию (например, адрес контакта нужного типа).
Это настраивается в свойствах поля в подзапросе:
subquery

такой вопрос
есть следующий подзапрос в sq_Opportunity

	(SELECT
		SUM([tbl_Cashflow].[BasicAmount]) AS [BasicAmount]
	FROM
		[dbo].[tbl_Cashflow] AS [_tbl_Cashflow]
	WHERE([tbl_Cashflow].[OpportunityID] = [tbl_Opportunity].[ID] AND
		[tbl_Cashflow].[UseAsPandL] = :True)) AS [TourCreditSum],

в датасете по этому подзапросу сформировано поле с дробным значением.
все выводит верно, но в гриде в поле итогов нет возможности суммировать всю колонку этого поля - только вывести количество, как будто это не численное поле

я так понял оно и не должно подсчитывать (так как итоги подсчитываются SQL-запросом в БД, а не на основе датасета). Верно?
http://www.community.terrasoft.ru/forum/topic/5193

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

Можно сделать view с подзапросом, создать и привязать к нему сервис таблицы и получать значение из неё как из обычной колонки.

Войдите или зарегистрируйтесь, чтобы комментировать

Добрый день.
Мне нужно создать сложный запрос на подсчет количества свободных продуктов в карточке Продукт в продаже с помощью сервиса Select Query. Теперь подробнее, у меня есть доработанная карточка Продукт в продаже в которой есть стандартные поля Quantity (Количество) и OfferingID (Продукт), а также 2 новых поля StartTime (Время начала бронирования) и StopTime (Время окончания бронирования). С помощью этих полей нужно сформировать запрос, который подсчитывал бы количество всех забронированных в промежуток с Времени начала бронирования по Время окончания бронирования продуктов одного вида при создание новой записи в детали Продукт в продаже в версии Terrasoft 3.3.1.104. Каким образом можно это реализовать?

У меня такой же вопрос

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

Здравствуйте!
Вам будет проще воспользоваться фильтрацией датасета по этим полям, используя фильтры сравнения .
Т.е. создаем два фильтра - (StartDate < Параметр.значение_даты) И (DueDate > Параметр.значение_даты) и далее:

//пролучаем Dataset
var Dataset = Services.GetNewItemByUSI(ds_Dataset);
//фильтруем
ApplyDatasetFilter(Dataset, 'StartDateFilterName', StartDate, true);
ApplyDatasetFilter(Dataset, 'DueDateFilterName', DueDate, true);
Dataset.Open();
var ItemsInDS = Dataset.RecordsCount;

В переменной ItemsInDS и будет количество записей удовлетворяющим условию.

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

Здравствуйте Террасофт!

В созданном "ФастРепорт" отчете реализована функция подстановки суммы прописью, следующим образом:

var
  ConvertUtils, CurrencyUtils: Variant;
   
procedure memSummaOnBeforePrint(Sender: TfrxComponent);
var
  Amount: String;
  AmountInStr: String;
begin
  Amount := FloatToStr(SUM(,ddOffering));
  AmountInStr := ConvertUtils.ScriptControl.CodeObject.AmountToStr(Amount, 'ru', 'RUB');                
  memSumma.Text := AmountInStr;  
end;

procedure frxReportOnStartReport(Sender: TfrxComponent);
var
  Connector: Variant;                                
begin
  Connector := ds_ReportInvoiceWithNDSForRussia11.GetConnector();
  ConvertUtils := Connector.Services.GetNewItemByUSI('scr_ConvertUtils');
  CurrencyUtils := Connector.Services.GetNewItemByUSI('scr_CurrencyUtils');          
end;

begin

end.

Подскажите как реализовать подстановку копеек цифрами, а остальное оставить, как было, буквами?

У меня такой же вопрос

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

Игорь, могу сказать, что у нас это рализовано, возможно, не самым оптимальным методом, поскольку дорабатывался этот функционал на заре знакомства с системой, но работает так:

function PartAmountInCurrencyToString(Dataset, SumString, UE, UEkopek, ValUE, ValUEkopek){
	var kopekString = SumString.substring(SumString.lastIndexOf(UEkopek),SumString.length);
	var rubleString = SumString.substring(SumString.lastIndexOf(UE),SumString.length);
    rubleString = rubleString.substring(0,rubleString.indexOf(' '));
 
	var rubleValSring = SumString.substring(0,SumString.indexOf(UE) - 1);
	Dataset.Values('SumString') = rubleValSring + ' ' +
	rubleString + ' ' + ValUEkopek + ' ' + kopekString;
}

В качестве SumString передается то, что у Вас лежит в AmountInStr. Затем происходит запись непосредственно в Датасет... Вы можете использовать просто переменную...

По другим параметрам:
пример вызова PartAmountInCurrencyToString(Dataset,SumString, 'руб', 'коп', ruble, kopek);
при этом

			//Рубли и копейки
		    var fullSum = Dataset.ValAsStr('Amount') 
			if(fullSum.lastIndexOf(",") == -1){
		 		fullSum = fullSum + ',00';
			}
			//если "круглое" число копеек
	    	if(fullSum.lastIndexOf(",") == fullSum.length - 2){
		  	fullSum = fullSum + '0';
			}
			var ruble =  fullSum.substring(0,fullSum.lastIndexOf(","));
			var kopek = fullSum.substring(fullSum.length - 2,fullSum.length);

Надеюсь, помогла :)

Для того, чтобы внести данные изменения, необходимо откорректировать скрипт scr_ConvertUtils:

Найдите строку

ko = Propis(price = kop, CurrencyOperations.K);

и замените ее на строку

ko = CurrencyOperations.K + " копеек";

Благодарю за ответы!
Алёна ваш метод достаточно трудоемок, если не найдется более простого примера обязательно воспользуюсь вашим, отдельная вам благодарность.

Анна пример предложенный вами не работает, скрипт срабатывает, но в результате вместо копеек цифрами, много раз повторяется слово:"копеек" в разных падежах.

"Alimova Anna" написал:Для того, чтобы внести данные изменения, необходимо откорректировать скрипт scr_ConvertUtils

Анна, а если в другом месте понадобится все строкой? Мы именно из этих соображений не стали менять основной скрипт, потому что в одном месте копейки нужны цифрами, а в другом прописью...

Игорь, в таком случае попробуйте заменить скрипт scr_ConvertUtils на скрипт в приложении.

Что менялось: в функции Propis добавлен фрагмент кода

	    if(D == CurrencyOperations.K){
        	litera = price + ' ' + edinicy.split(/[\s\!,\.\?]+/g).pop();
			return litera;
        }

и в следующем фрагменте

	ko != '' ? res = ru + ' ' + ko: res = ru;
	if (CurrencyOperations.Language == 'ru') {
		ru == 'Ноль ' + CurrencyOperations.R[0] && ko != ''? res = ko: 0;
		kop == 0? res += ' ноль ' + CurrencyOperations.K[0]: 0;
	} else {
		ru == 'Нуль ' + CurrencyOperations.R[0] && ko != ''? res = ko: 0;
		kop == 0? res += ' нуль ' + CurrencyOperations.K[0]: 0;
	}

заменены строки ' ноль ' на цифру.

Алена, если Вас в разных отчетах нужно по-разному отображать копейки, тогда имеет смысл модифицировать функцию Propis:
1. Добавить в нее дополнительный параметр - копейки цифрами или буквами
2. Вызывать добавленный мною фрагмент кода по условию kopnum == true

	    if((D == CurrencyOperations.K)&&(kopnum == true)){
        	litera = price + ' ' + edinicy.split(/[\s\!,\.\?]+/g).pop();
			return litera;
        }

Аналогично поступить с фрагментом кода 0 копеек

Анна спасибо вам, теперь все работает как надо. До конца только не понял, как пользоваться этим:
-----------------------
Алена, если Вас в разных отчетах нужно по-разному отображать копейки, тогда имеет смысл модифицировать функцию Propis:
1. Добавить в нее дополнительный параметр - копейки цифрами или буквами
2. Вызывать добавленный мною фрагмент кода по условию kopnum == true

if((D == CurrencyOperations.K)&&(kopnum == true)){
litera = price + ' ' + edinicy.split(/[\s\!,\.\?]+/g).pop();
return litera;
}
Аналогично поступить с фрагментом кода 0 копеек
---------------------------------------------

Видимо вызов: "ConvertUtils.ScriptControl.CodeObject.AmountToStr(Amount, 'ru', 'RUB');" будет видоизменен? Если да то подскажите как? Если нет, получается, необходимо отлавливать отчет в котором запускается этот скрипт?

Анна, спасибо! Интересный вариант :) Вносить изменения в функцию побоялись по той причине, что "мало ли где еще она вызывается"

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

В большинстве случаев, в отчетах надо выводить некую итоговую информацию: сумму, количество и т.п. В FastReport, для этих целей, существуют так называемые агрегатные функции:

  • [SUM] Возвращает сумму заданного выражения
  • [MIN] Возвращает минимальное значение заданного выражения
  • [MAX] Возвращает максимальное значение заданного выражения
  • [AVG] Возвращает среднее значение заданного выражения
  • [COUNT] Возвращает количество строк в диапазоне данных

С их помощью можно подсчитать функцию от определенного значения по диапазону данных.

Для того чтобы агрегатная функция работала корректно, необходимо добавить в структуру отчета элемент Footer и поместить функцию в тело Footer-a:
a1

Результат:
a2

Поделиться

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

Предлагаю один из вариантов решения поставленной задачи.

1. В ds_InvoiceScript добавить функцию:

function ChangeCurrencyID(InvoiceID, CurrencyID) {
  if (IsEmptyValue(InvoiceID) || IsEmptyValue(CurrencyID)) {
   return;
   }
  if (!Assigned(InvoiceScript.OffDataset)) {
   InvoiceScript.OffDataset =
   Services.GetNewItemByUSI('ds_OfferingInInvoice');
   }
 var Dataset = InvoiceScript.OffDataset;
  Dataset.DisableEvents();
  ApplyDatasetFilter(Dataset, 'InvoiceID', InvoiceID, true);
  Dataset.Open();
 while (!Dataset.IsEOF) {
   Dataset.Edit();
   Dataset.Values('CurrencyID') = CurrencyID;
   Dataset.Post();
   Dataset.GotoNext();
  }
ApplyDatasetFilter(Dataset, 'InvoiceID', InvoiceID, false);
Dataset.Close();
}

2. В обработчике события OnDatasetAfterPost счета вставить вызов функции:
ChangeCurrencyID(Dataset.Values('ID'), Dataset.Values('CurrencyID'));

3. Сохранить все внесенные изменения. Перезапустить приложение и протестировать работоспособность системы.

Желаю удачи!

С уважением,
Мельникова Екатерина

Поделиться

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

Судя по функции, она делает только замену валюты в продуктах счета. А пересчет где делается?

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

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

У меня такой же вопрос

3 комментария

Добрый день.

Для того, чтобы достичь желаемого результата Вам необходимо разместить элементы таким образом, как на вложеном рисунке.

Terrasoft Support Team

А как сделать так, чтобы PageFooter не печатался на последней странице отчета.

Добрый день.

Для того, чтобы не выводить PageFooter на последней странице Вы можете сделать двухпроходный отчет. Это позволит Вам сосчитать количество страниц отчета. После того, как Вы узнаете количество страниц totalpages, Dы можете воспользоваться свойством PageFooter Visible. Условие вывода элемента отчета необходимо прописать в скрипте. Это можно сделать в соответствии событию OnBeforePrint.

На данный момент мы не имеем подобной реализованной функциональности. С аспектами использования вышеприведенных свойств Вы можете ознакомиться на форуме разработчиков Fast Report и в руководстве пользователя и разработчика Fast Report.

Без использования доработок скрипта скрывать Page Footer на последней странице отчета невозможно.

Terrasoft Support Team

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

Рассмотрим реализацию функционала на конкретном примере.Видоизменяем карточку контакта для собственных нужд: создаем отдельные поля "Фамилия", "Имя", "Отчество". Но также оставляем поле "ФИО", которое должно заполняться автоматически на основании суммы значений в вышеуказанных полях.

Для реализации подобного функционала во-первых, требуется создать функцию, которая будет заполнять поле ФИО. Эту функцию можно создать вначале скрипта, в котором будет обработчик события OnDatasetDataChange:

function CreateName(Dataset) {
var FirstName = Dataset.Values('FirstName');
FirstName = (IsEmptyValue(FirstName) ? '' : ' ' + FirstName);
var Surname = Dataset.Values('Surname');
Surname = (IsEmptyValue(Surname) ? '' : Surname);
var PatronymicName = Dataset.Values('PatronymicName');
PatronymicName = (IsEmptyValue(PatronymicName) ? '' : ' ' + PatronymicName);
Dataset.Values('Name') = Surname + FirstName + PatronymicName;
}

Затем на событии OnDatasetDataChange датасета необходимо для каждого из полей вызывать созданную предварительно функцию:

function SelfOnDatasetDataChange(DataField) {
var Dataset = DataField.ParentDataFields.ParentDataset;
if (DataField.Name == 'Surname') {
CreateName(Dataset);
return;
}
if (DataField.Name == 'FirstName') {
CreateName(Dataset);
return;
}
if (DataField.Name == 'PatronymicName') {
CreateName(Dataset);
return;
}
if ((Contact.IsUpdating || !Assigned(DataField) ||
(IsEmpty(DataField.Value)))) {
return;
};
}

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

Поделиться

0 комментариев
Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Здравствуйте!!
Написала скрипт, который при изменениии даты (PaymentDate)в карточке счета (tbl_Invoice)должен суммировать значения полей "Сумма" (Amount) таблицы операций (tbl_Cashflow)и заносить посчитанный результат в поле "Сумма оплаты" (PaymentAmount) таблицы "Счет" (tbl_Invoice).

Код написан внутри скрипта ds_InvoiceScript и выглядет следующим образом:
function DataChange(DataField){
.....
case ('PaymentDate'):
InvoiceScript.OnDataChangeDisabled = true;
try {
var InvoiceID = DataFields.ItemsByName('InvoiceID').Value;
var PaymentAmount = DataFields.ItemsByName('PaymentAmount').Value;
var Summ = GetDetailSummary('tbl_Cashflow', 'InvoiceID', InvoiceID, 'Amount', stSum);
if (IsEmptyValue(Summ))
{
Summ = 0;
}
SetFloatDataFieldWithRound(DataFields.ItemsByName('PaymentAmount'), Summ);
}
finally{
InvoiceScript.OnDataChangeDisabled = false;
}
break;
}
}
При попытке же изменить дату выдается ошибка: "Ошибка выполнения метода 'SelfOnDatasetDataChange".
Помогите, пожалуйста разобраться в чем дело.
С уважением, Гашникова Екатерина

У меня такой же вопрос

2 комментария

Добрый день, Екатерина!

Ошибка в строке:
var InvoiceID = DataFields.ItemsByName('InvoiceID').Value;
правильный вариант:
var InvoiceID = DataFields.ItemsByName('ID').Value;

Проверил, работает.
Желаю успехов!

Спасибо, большое!!!
Все заработало

Войдите или зарегистрируйтесь, чтобы комментировать