SSRS Iif оценивает True и False

MSDN заявляет, что SSRS будет оценивать как истинную, так и ложную часть оператора Iif независимо от того, какой из них будет возвращен. Кажется, это делает Iif совершенно бесполезным с точки зрения предотвращения ошибок. Другими словами, вы не можете использовать Iif для обхода ошибки, поэтому, по сути, любая операция, которую вы решите включить, всегда должна быть допустимой, независимо от условий. Честно говоря, что хорошего в этом?

Итак, мой вопрос: есть ли у SSRS другие способы оценки условий, кроме Iif?

Вот мой пример. Я просто хочу иметь возможность вернуть Left, не захватывая первый символ совпадения.

=Iif
(
    InStr(Fields!SearchField.Value, Fields!Criteria.Value) <= 1,    
    "",             
    Left(Fields!SearchField.Value, InStr(Fields!SearchField.Value, Fields!Criteria.Value)-1)                    
)

Однако здесь происходит то, что InStr(Fields!Criteria.Value, Fields!Criteria.Value)-1 в некоторых случаях оценивается как 0, что совершенно нормально, пока FALSE часть оператора не попытается вычесть из него 1 и передать его в функцию InStr. InStr не может принимать -1 в качестве количества возвращаемых символов.

В упрощенном виде это выглядит следующим образом. Предположим, у вас есть ситуация, когда Value никогда не может упасть ниже 0 без возникновения ошибки.

Iif (Value > 0, Value = Value -1, 0)

Попытка использовать Iif, чтобы значение не опускалось ниже 0, не работает, потому что все эти операторы оцениваются, даже если они не соответствуют условиям.

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


person Aaron Rheams    schedule 30.01.2018    source источник
comment
Я думал, что SSRS до недавнего времени сам использовал оценку bool с коротким замыканием. IIF() — это функция, и все выражения оцениваются до выполнения сравнения. Вы можете поместить свое выражение в код отчета и присвоить значение, например Code.FormatWhenFoundOrEmpty(x,y)   -  person Ross Bush    schedule 30.01.2018
comment
Мне кажется, или это крайне недальновидно со стороны Microsoft? Я имею в виду, что вся идея условных выражений заключается в том, чтобы делать что-то, когда выполняется условие, и не делать этого в противном случае. Вероятно, важно отметить, что это действительно нелогичная ситуация. Я был очень удивлен, столкнувшись с этим.   -  person Aaron Rheams    schedule 30.01.2018


Ответы (4)


Я тоже думал, что Switch будет работать, но при тестировании это не сработало. Насколько я могу судить, собственный код — единственный выход. Я протестировал приведенную ниже функцию, которая работала для моих нескольких тестовых случаев.

Public Function TruncateWord(ByVal str As String, ByVal criteria As String) As String
If str.Contains(criteria) Then
    Return Left(str, InStr(str, criteria) - 1)
Else:
    Return ""
End If
End Function

Я протестировал следующие 5 основных строк, ища «d», и получил следующие результаты:

+-----------------+
| String | Result |
+-----------------+
| asdf   | as     |
| asd    | as     |
| as     |        |
| da     |        |
| ad     | a      |
+-----------------+

Таким образом, это работает для всех трех возможных случаев (InStr возвращает> 1, InStr возвращает 1 и InStr возвращает 0) из моего ограниченного тестирования.

person C Black    schedule 30.01.2018
comment
Большое Вам спасибо. Я думаю, это сработает. Я надеялся избежать пользовательского кода, но если это единственный способ, мне определенно придется пойти по этому пути. - person Aaron Rheams; 30.01.2018

Вот окончательный результат предложения Си Блэка использовать пользовательский код. В конце концов я надеялся использовать сегмент строки для форматирования соответствия другим цветом в противоположном столбце. Мне пришлось добавить несколько html-тегов. Это работает отлично. Спасибо всем за вашу помощь.

Блок кода:

Public Function ParseMatch (ByVal FullString As String, ByVal Criteria As String) As String

    Dim Segment(2) As String
    Dim Result As String

    If FullString.ToUpper.Contains(Criteria.ToUpper)

        Segment(0) = Left(FullString, InStr(Ucase(FullString), Ucase(Criteria) )-1 )
        Segment(1) = Criteria
        Segment(2) = Right(FullString, Len(FullString) - Len(Segment(0)) - Len(Criteria))

        Result = Segment(0) & "<b><FONT color=blue>" & Segment(1) & "</FONT></b>" & Segment(2)

    Else
        Result = FullString
    End If

    Return Result

End Function

Ячейка отчета:

=Code.ParseMatch(Fields!Defendants.Value, Fields!Firm_Client_Name.Value)

Если имя встречается в списке ответчиков, оно окрашивает текст в этом поле в синий цвет и выделяет его жирным шрифтом.

person Aaron Rheams    schedule 31.01.2018

Используйте 1_

SWITCH прекращает вычисление выражения, как только будет найдено первое значение True. Switch работает с парами (выражение для оценки и результат, если оно истинно). Конечный True действует как else.

=SWITCH
(
InStr(Fields!SearchField.Value, Fields!Criteria.Value) <= 1, "",
True, Left(Fields!SearchField.Value, InStr(Fields!Criteria.Value, Fields!Criteria.Value)-1)                   
)
person Alan Schofield    schedule 30.01.2018
comment
Спасибо, Алан! Я попробую это и посмотрю, смогу ли я исправить проблему. - person Aaron Rheams; 30.01.2018
comment
На самом деле, это дает точно такие же результаты. Я внес изменения выше, потому что у меня были неправильные поля образца. Однако они верны в реальном коде. Хотя такая же ситуация. Это не создаст ценность и не остановится на достигнутом. - person Aaron Rheams; 30.01.2018
comment
Я даже явно определил условие как InStr(Fields!SearchField.Value, Fields!Criteria.Value) › 1 Никакой радости. - person Aaron Rheams; 30.01.2018
comment
Я посмотрю позже, если будет возможность. Можете ли вы дать 2 или 3 примера значений для каждого поля? - person Alan Schofield; 30.01.2018
comment
Увидеть ниже. Спасибо. - person Aaron Rheams; 30.01.2018

Я переписал его для удобства чтения:

=Switch
(
    InStr(Fields!Defendants.Value, Fields!Firm_Client_Name.Value) = 0, "",  
    InStr(Fields!Defendants.Value, Fields!Firm_Client_Name.Value) = 1, "",  
    True, Left(Fields!Defendants.Value, InStr(Fields!Defendants.Value, Fields!Firm_Client_Name.Value)-1)
)

0 = ошибка

' 1 =

' >1 = подстрока на основе критериев

1 и >1 верны, но я все еще получаю сообщение об ошибке, когда InStr оценивается как 0.

Дело в том, что я должен сказать функции Left -1, иначе она вернет первую букву разделителя, чего я не хочу. Несмотря на то, что условие InStr(Fields!Defendants.Value, Fields!Firm_Client_Name.Value) = 0 истинно, вместо возврата "" для столбца возвращается ошибка. Это говорит мне, что он все еще оценивается, несмотря на то, что он находится за пределами указанного условия.

Если я опускаю -1 в функции Left, ошибки не возникает. Тем не менее я получаю подстроку + первую букву разделителя.

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

person Aaron Rheams    schedule 30.01.2018
comment
Можете ли вы предоставить образцы данных для каждого поля, даже если вы их выдумываете, и ожидаемые результаты в каждом случае. - person Alan Schofield; 30.01.2018