Set Language for MESSAGE statement - abap

I access my coding in batch mode with a set system user via RFC, whose logon language is set to 'DE'. In case of an error, I use a message statement, so the application on the other system can handle this error.
MESSAGE i001(ztest) INTO DATA(e_error).
The message is translated in several languages. Depending on the language of the user on the other system, I need the message translated. But regardless of changing sy-langu or using SET (LOCALE) LANGUAGE statement, the message is still returned in german, the system users original setting (As stated in keyword documentation 'If the text environment is set using the statement SET LOCALE, this is ignored by the language in which the message is displayed. '
Before this change we used text elements, with which it worked.
Is it possible to change the language the MESSAGE statement uses while runtime?

A second possible workaround is to :
make your RFC-enabled function module (RFM 1) return the message ID + message number + 4 optional variables
after calling the RFM 1, the calling program calls the RFC-enabled function module BAPI_MESSAGE_GETDETAIL to get the text in the desired language (parameter LANGUAGE or LANGUAGE_ISO).

A workaround could be, instead of using MESSAGE, just selecting the text of the message with the language you need (English in my example):
SELECT SINGLE text
INTO #DATA(e_error)
FROM t100
WHERE sprsl EQ 'E'
AND arbgb EQ 'ZTEST'
AND msgnr EQ '001'.
Obviously, if the message has placeholder(s), you have some more work to do.

Related

Why Language Key is displayed like 1 character instead of 2?

I was trying to learn how to use String Templates and encountering displaying characters.
What I was trying to display is:
SAP Logon Language Key EN
using this line of code:
WRITE: |{ text-003 } { sy-langu }|.
But instead, it only displays:
SAP Logon Language Key E
it only displays the first character of the language instead of the full 2 letters which are EN
SAP language codes are displayed as two letters, but are internally stored as just one. There are various data-types where the internal and the external representation differ. It's called a conversion-routine and it's defined on the level of the domain in the ABAP dictionary.
If you want to convert to the external representation of a language field, use the function module CONVERSION_EXIT_ISOLA_OUTPUT. If you want to do the reverse - convert a UI representation to the database representation - use CONVERSION_EXIT_ISOLA_INPUT.
To complete Philipp answer, you may also use WRITE to convert from database to external representation, it will automatically search the right conversion routine (ISOLA when it's about SY-LANGU):
DATA display_language_code TYPE c LENGTH 2.
WRITE sy-langu TO display_language_code.
ASSERT display_language_code = 'EN'.

Can we set multiple DCM_SpecificCharacterSet while importing records using DICOM?

Currently, I am using the below code to set parameters to retrieve data from PACS.
DcmDataset findParams = DcmDataset();
findParams.putAndInsertString(DCM_QueryRetrieveLevel, "SERIES");
findParams.putAndInsertString(DCM_SpecificCharacterSet, "ISO_IR 192");
However, just wanted to check can we provide support multiple characters set to import data at the same time, Code will look like something below, I am trying to check whether this is possible or not as I dont have the facility to verify the same.
findParams.putAndInsertString(DCM_SpecificCharacterSet, "ISO_IR 192" ,"ISO_IR 100");
I think that what you want to express is that "this Query SCU can accept responses in the following character sets". This is plainly not possible. See a discussion in the DICOM newsgroup for reference. It ends with a proposal to add character set negotiation to the association negotiation. But such a supplement has not been submitted yet, and I am not aware of anyone working on it currently.
The semantics of the attribute Specific Character Set (0008,0005) in the context of the Query Retrieve Service Class:
PS3.4, C.4.1.1.3.1 Request Identifier Structure
Conditionally, the Attribute Specific Character Set (0008,0005). This Attribute shall be included if expanded or replacement character sets may be used in any of the Attributes in the Request Identifier. It shall not be included otherwise
I.e. it describes nothing but the character encoding of your request dataset.
and
C.4.1.1.3.2 Response Identifier Structure
Conditionally, the Attribute Specific Character Set (0008,0005). This Attribute shall be included if expanded or replacement character sets may be used in any of the Attributes in the Response Identifier. It shall not be included otherwise. The C-FIND SCP is not required to return responses in the Specific Character Set requested by the SCU if that character set is not supported by the SCP. The SCP may return responses with a different Specific Character Set.
I.e. you cannot control the character set in which the SCP will send you the responses. Surprising but a matter of fact.
Sending multiple values for the attribute is possible but has different semantics. It means that the request contains characters from different character sets which are switched using Code Extension Techniques as defined in ISO 2022. An illustrative example how this would look like and what it would mean is found in PS3.5, H.3.2
What implementors usually do to avoid character set compatibility issues is configuring "the one and only" character set for a particular installation (=hospital) in a locale configuration that is configured upon system setup. It works pretty well, for e.g. an installation in Russia will very likely support Cyrillic (ISO_IR 144) or UNICODE (ISO_IR 192) or both. In case of "both", you can select the character set that you prefer for configuring your system.

Number of formal parameters is larger than the number of actual parameters

So when I try to compile (activate), the compiler throws this error message:
Different number of parameters in FORM and PERFORM (routine:
CALL_CALCULATE_TAX_ITEM, number of formal parameters: 7, number of
actual parameters: 6)
It refers to the line 169 in the include LJ_1B_NFE_INF3B, where there is this statement:
PERFORM call_calculate_tax_item
USING
ls_rbkpv
ls_drseg
ls_j_lbaa
ls_lfa1
ls_xmlpo
abap_true
CHANGING
et_bapiret2[].
Here is the form code:
FORM call_calculate_tax_item
USING ls_rbkpv TYPE mrm_rbkpv
ls_drseg TYPE mmcr_drseg
ls_j_1baa TYPE j_1baa
ls_lfa1 TYPE lfa1
ls_xmlpo TYPE ty_xmlpo_ext "1843823
lv_get_conditions TYPE flag "2142110
CHANGING et_bapiret2 TYPE bapirettab.
So, it's obvious that there are 7 parameters both in PERFORM and FORM, why does the compiler say that there are only 6 actual parameters?
Thanks and sorry for broken English.
Usually such problems result from a not fully implemented SAP Note or not activating all the changes made by the note at the very same time.
In your case I see that either SAP Note 2142110 is not fully implemented or some of the changes resulting from the implementation of it have not been activated.

How can I ask user to enter the input in PostgresSQL/plpgsql?

Hi I want to take input from user in my
DO BEGIN and END block...
I tried to use /prompt inside but it doesnt work.
Do we have any other way that we can use it inside function or block in postgres?
Important note: PLpgSQL is server side only language - there is not any possibility do any user interactivity operation. You have to collect input on client side before start of PLpgSQL code, and user input push there as parameters.
DO statement is server side statement, so you cannot do any interactive action there.
DO statement doesn't support parameters so it is not easy push any parameters inside DO statement, but is possible with custom configuration variables:
\prompt 'enter some text: ' psqlvar
\o /dev/null
select set_config('psql.psqlvar', :'psqlvar', false);
\o
do $$
DECLARE var text = current_setting('psql.psqlvar');
BEGIN
RAISE NOTICE 'entered text is: %', var;
END;
$$;
The function set_config is used to moving a content of client variable :psqlvar to server side - session variable psql.psqlvar. The content of this server side variable is taken by function current_setting.
You have to separate in your mind server side and client side content. The DO statement is evaluated on server side. The psql \prompt command is evaluated on client side.
As bad ideas go, asking for user input in a stored procedure is up there with using usernames as session identifiers. This is a really, really bad idea. Yes there are ways in some environmnets to do this. But just because you can does not mean you should. For example I have heard of people using pl/python to make a network connection back to the client computer and ask for more information. However, this is frankly DailyWTF territory. It also assumes a protocol and listener on the client to ask for this request and therefore doesn't work from pgadmin.
Now, DO creates an anonymous function without arguments and immediately executes it. This seems to be where your real problem is.
Your best solution is to just create an actual function with arguments and accept the input there. Then it can be used anywhere. And you can re-use, modify security, etc. This sounds like it is exactly what you need.
Failing that you could preprocess your do block before you send it.
Your best design where you want to reuse PL/PGSQL code with inputs is to use a function (see CREATE FUNCTION) instead of DO (note you can put these in another schema if that is a concern).

Get Text Symbol Programmatically With ID

Is there any way of programmatically getting the value of a Text Symbol at runtime?
The scenario is that I have a simple report that calls a function module. I receive an exported parameter in variable LV_MSG of type CHAR1. This indicates a certain status message created in the program, for instance F (Fail), X (Match) or E (Error). I currently use a CASE statement to switch on LV_MSG and fill another variable with a short description of the message. These descriptions are maintained as text symbols that I retrieve at compile time with text-MS# where # is the same as the possible returns of LV_MSG, for instance text-MSX has the value "Exact Match Found".
Now it seems to me that the entire CASE statement is unnecessary as I could just assign to my description variable the value of the text symbol with ID 'MS' + LV_MSG (pseudocode, would use CONCATENATE). Now my issue is how I can find a text symbol based on the String representation of its ID at runtime. Is this even possible?
If it is, my code would look cleaner and I wouldn't have to update my actual code when new messages are added in the function module, as I would simply have to add a new text symbol. But would this approach be any faster or would it in fact degrade the report's performance?
Personally, I would probably define a domain and use the fixed values of the domain to represent the values. This way, you would even get around the string concatenation. You can use the function module DD_DOMVALUE_TEXT_GET to easily access the language-dependent text of a domain value.
To access the text elements of a program, use a function module like READ_TEXT_ELEMENTS.
Be aware that generic programming like this will definitely slow down your program. Whether it would make your code look cleaner is in the eye of the beholder - if the values change rarely, I don't see why a simple CASE statement should be inferior to some generic text access.
Hope I understand you correctly but here goes. This is possible with a little trickery, all the text symbols in a report are defined as variables in the program (with the name text-abc where abc is the text ID). So you can use the following:
data: lt_all_text type standard table of textpool with default key,
lsr_text type ref to textpool.
"Load texts - you will only want to do this once
read textpool sy-repid into lt_all_text language sy-langu.
sort lt_all_Text by entry.
"Find a text, the field KEY is the text ID without TEXT-
read table lt_all_text with key entry = i_wanted_text
reference into lsr_text binary search.
If you want the address you can add:
field-symbols: <l_text> type any.
data l_name type string.
data lr_address type ref to data.
concatenate 'TEXT-' lsr_text->key into l_name.
assign (l_name) to <l_text>.
if sy-subrc = 0.
get reference of <l_text> into lr_address.
endif.
As vwegert pointed out this is probably not the best solution, for error handling rather use message classes or exception objects. This is useful in other cases though so now you know how.