FM for printing ZPL causes deadlock - abap

I did create a ABAP report to print some ZPL which works fine. Now my goal is to transfer that logic into a FM to be able to call it wherever and however I want. Problem is that doing so causes my SAPGUI to deadlock itself for like 10 minutes and show me a message saying "rolling area is to small".
In order to print the ZPL I used this guides:
https://answers.sap.com/questions/3535287/printing-zpl-code-directly-to-a-printer.html
https://blogs.sap.com/2021/07/01/print-barcode-on-zebra-printer-directly-from-abap-report-without-form/
This is the most stripped down code I tested:
call function 'GET_PRINT_PARAMETERS'
exporting
destination = 'WA06'
copies = 1
list_name = 'TEST'
list_text = 'Test NEW-PAGE PRINT ON'
immediately = 'X'
release = ' '
new_list_id = 'X'
expiration = 2
layout = 'G_RAW'
sap_cover_page = 'X'
receiver = sy-uname
department = 'System'
no_dialog = abap_false
line_count = 60
importing
out_parameters = params
valid = valid.
if valid <> space.
new-page print on parameters params no dialog.
format color off intensified off.
print-control function 'BCPFX'.
write: / ' :NEW-PAGE'.
write: / ' ^XA ' .
write: / ' ^FO040,040^A0N,40,40^FDHello World^FS '.
write: / ' ^XZ ' .
write: / ' ^FX End of Job'.
endif.
It basically just calles GET_PRINT_PARAMETERS, does some printer control voodoo and then writes the lines. This works perfectly fine when I execute that out of a SE38 report. But does absolutly nothing past showing me the printer settings windows and entering it. It just runs for like 10 minutes and then shows me the scrolling area is too small error which just goes away as soon as I try to hit F1 for help.
I managed to debug that FM to an extent so that I understand now that the problem lies not in my program but somewhere in the the surrounding SFCS_FA_TEST_FUNCTION FM or to be more precise, the deadlock occures on line 271 when executing SFCS_FA_OUTPUT_LIST, which consequently has a check from line 48 onwards
* Und dann das Ganze ausgeben
IF rseumod-fbalv_grid = space.
CALL SCREEN 500.
ELSE.
CALL SCREEN 800. " ec: ALV-Darstellung
ENDIF.
Here the CALL SCREEN 500 gets called over and over and over.
Has anyone experienced the same problem and can help me solving it?

The problem seems to be the SE37 environment. The fact that I try to write to a printer in a FM. If I call the FM from a normal report then all works out as expected.

Related

Word automation failing on server, but dev station works great

I am automating a oft-used paper form by querying the user on a web page, then modifying a base Word document and feeding that modified doc file to the user's browser for hand-off to Word.
The code is Visual Basic, and I am using the Microsoft.Office.Interop module to manipulate the document by manipulating Word. Works fine on the development system (Visual Studio 2015) but not on the production server (IIS 8.5).
Both the Documents.Open() call and the doc.SaveAs() call fail with Message="Command failed" Source="Microsoft Word" HResult=0x800A1066
Things I've tried:
Added debugging out the whazoo: Single-stepping is not an option on the production machine, so I pinpointed the problem lines with debug output.
Googled and found that this problem has been reported as early as 2007, but no viable solutions were reported.
A couple sites mentioned timing issues, so I added several pauses and retries -- none helped.
Some mentioned privileging, so I tried changing file permissions & application pool users -- neither helped.
Enhanced my exception handling reports to show more details and include all inner exceptions. That yielded the magic number 800A1066 which led to many more google hits, but no answers.
Added fall-back code: if you can't open the main document, create a simple one. That's when I found the SaveAs() call also failing.
Dropped back to the development system several times to confirm that yes, the code does still work properly in the right environment.
Greatly condensed sample code does not include fallback logic. My Word document has a number of fields whose names match the XML tokens passed as parameters into this function. saveFields() is an array of those names.
Dim oWord As Word.Application
Dim oDoc As Word.Document
oWord = CreateObject("Word.Application")
oWord.Visible = True
oDoc = oWord.Documents.Open(docName)
Dim ev As String
For i = 0 To saveFields.Length - 1
Try
ev = dataXD.Elements(saveFields(i))(0).Value
Catch
ev = Nothing
End Try
If ev IsNot Nothing Then
Try
Dim field = oDoc.FormFields(saveFields(i))
If field IsNot Nothing Then
If field.Type = Word.WdFieldType.wdFieldFormTextInput Then
field.Result = ev
End If
End If
Catch e As Exception
ErrorOut("Caught exception! " & e.Message)
End Try
End If
Next
...
oDoc.SaveAs2(localDir & filename)
oDoc.Close()
oWord.Quit(0, 0, 0)
The code should generate a modified form (fields filled in with data from the parameters); instead it fails to open, and the fallback code fails to save the new document.
On my dev system the document gets modified as it should, and if I break at the right place and change the right variable, the fallback code runs and generates the alternate document successfully -- but on the production server both paths fail with the same error.
Barring any better answers here, my next steps are to examine and use OpenXML and/or DocX, but making a few changes to the existing code is far preferable to picking a new tool and starting over from scratch.
Unfortunately, Lex Li was absolutely correct, and of course, the link to the reason why is posted on a site my company considers off limits, thus never showed up in my google searches prior to coding this out.
None of the tools I tried were able to handle the form I was trying to automate either -- I needed to fill in named fields and check/uncheck checkboxes, abilities which seemed beyond (or terribly convoluted in) the tools I evaluated ...
Eventually I dug into the document.xml format myself; I developed a function to modify the XML to check a named checkbox, and manipulated the raw document.xml to replace text fields with *-delimited token names. This reduced all of the necessary changes to simple string manipulation -- the rest was trivial.
The tool is 100% home-grown, not dependent upon any non-System libraries and works 100% for this particular form. It is not a generic solution by any stretch, and I suspect the document.xml file will need manual changes if and when the document is ever revised.
But for this particular problem -- it is a solution.
This was the closest I got to a complicated part. This function will check (but not uncheck) a named checkbox from a document.xml if the given condition is true.
Private Shared Function markCheckbox(xmlString As String, cbName As String, checkValue As Boolean) As String
markCheckbox = xmlString
If checkValue Then ' Checkbox needs to be checked, proceed
Dim pos As Integer = markCheckbox.IndexOf("<w:ffData><w:name w:val=""" & cbName & """/>")
If pos > -1 Then ' We have a checkbox
Dim endPos As Integer = markCheckbox.IndexOf("</w:ffData>", pos+1)
Dim cbEnd As Integer = markCheckbox.IndexOf("</w:checkBox>", pos+1)
If endPos > cbEnd AndAlso cbEnd > -1 Then ' Have found the appropriate w:ffData element (pos -> endPos) and the included insert point (cbEnd)
markCheckbox = markCheckbox.Substring(0, cbEnd) & "<w:checked/>" & markCheckbox.Substring(cbEnd)
End If
' Any other logic conditions, return the original XML string unmangled.
End If
End If
End Function

How to make statement that does more than 2 if condition is completed?

I'm making a Windows vb.net form application in Visual Studio 2015, where user can either preview an image in a PictureBox by importing it from a file dialog browser, or from a web url. If the user chooses to import it from its computer using the file dialog, the preview will automatically load once it has selected the image file.
If user accidentally fills both url and file dialog, i want to clear the TextBox of the url (called url_cover), the TextBox displaying the name of file imported in file dialog (called Browse.FileName) and the PictureBox preview (called preview), and also display a MessageBox telling user to try again, using only one of the import options.
I've already tried making a basic if statement which (until there everything normal) :
If url_cover.Text <> Nothing And Browse.FileName <> Nothing Then
MsgBox("Please do not import image using both file browser and URL.", [vbOKOnly], "Warning")
url_cover.Clear() Browse.FileName = Nothing preview.Enabled = False
I was expecting all these things to happen if i filled both url and file browser, but i came out with an error telling me that an end of statement was expected after the second instruction (which is url_cover.Clear()).
I tried switching the order in which the three instructions had to be executed, but every time it was the same, after the second instruction, an end of statement was expected...
Hope my explanations have been clear, and my question is how can i execute more than 2 instructions after the condition of my If statement has been completed.
If you want more than one statement to execute if a condition is met, then you need to enclose it in a block that ends with End If.
Your code will only execute the messagebox if the conditions are satisfied and then try to execute the rest whether the condition is met or not. You're getting the End Of Statement Expected error because you're trying to put several statements on one line.
Try this ..
If url_cover.Text <> Nothing And Browse.FileName <> Nothing Then
MsgBox("Please do not import image using both file browser and URL.", [vbOKOnly], Warning")
url_cover.Clear()
Browse.FileName = Nothing
preview.Enabled = False
End If
Try this out... You can use : to separate statements if you want them on one line.
If Not String.IsNullOrEmpty(url_cover.Text) AndAlso Not String.IsNullOrEmpty(Browse.FileName) Then MsgBox("Please do not import image using both file browser and URL.", [vbOKOnly], "Warning") : url_cover.Clear() : Browse.FileName = String.Empty : preview.Enabled = False
Or block...
If url_cover.Text <> Nothing And Browse.FileName <> Nothing Then
MsgBox("Please do not import image using both file browser and URL.", [vbOKOnly], "Warning")
url_cover.Clear()
Browse.FileName = Nothing
preview.Enabled = False
End If
IMHO, look into String.IsNullOrEmpty, Multiple statements in one line and the AndAlso operator. Also try to avoid the :, if statements can become long, obscure readability etc, but nothing is wrong in using it.
Please consider adding a comment if you think this post can be improved.

"Invalid Object Format Name" in Crystal Reports

When working with Crystal Report Field Objects and attempting to set "EnableSuppress" to False or alter the position or width of a field object is generating an "Invalid Object Format Name" error. The debugger shows all my code running without error until attempting to actually load the report. At that point, it will run the first couple without problem, then it fails when messing with a field object, and none of the rest will run. The code is shown below. Everything that generates an error is a FieldObject, but not all fieldObjects generate errors. In the code below, everything in Section2 is a TextObject and everything in Section3 is a FieldObject.
If condition = True Then
'Lines marked as runs ok, only run when a line that generates an error is not present before it.
Report.Section2.ReportObjects("Text7").Left = 7830 'Runs ok
Report.Section3.ReportObjects("Field4").Left = 8085 'Runs ok
Report.Section2.ReportObjects("Text13").ObjectFormat.EnableSuppress = False 'Runs ok
Report.Section3.ReportObjects("Field28").ObjectFormat.EnableSuppress = False 'error
Report.Section2.ReportObjects("Text9").Left = 10830 'Runs ok
Report.Section3.ReportObjects("Field23").Left = 10830 'error
Report.Section3.ReportObjects("Field23").Width = 615 'error
Report.Section2.ReportObjects("Text10").Left = 11445 'Runs ok
Report.Section3.ReportObjects("Field25").Left = 11445 'Runs ok
End If
Unless you figure out what is different about the fields that throw errors and are absolutely set on formatting in VB code, I suggest that you do your formatting from within the Crystal report. You obviously know about the conditional suppression and to change size and location of a field you can right-clicking on the field and clicking "Size and Position". There is also an option for conditional placement (formula).
Hope that helps,
Chris

Method 'range' of object _global failed when doing nothing

I have a big macro which basically processes some columns and spits out results based on some cross-checking with an access 2003 database. It works absolutely fine - no hitches at all.
However, I recently had to make a modification to it. It was literally changing an '8' to a '9' in one line of the code. But next time I ran it, it threw the 1004: Method 'Range' of object '_Global' failed error. Excel 2003 is a funny thing - I once scratched my head for hours over this, trying to find offending lines of code that could be causing the error, but alas to no avail. I did something that I didn't expect to trigger anything:
Starting with the original macro (100% confirmed working), if I just open the code up, and then save it so the 'last updated' metadata will update to reflect the save, though absolutely nothing has changed, it will throw that error again on opening.
It's as if it's so fragile that saving the macro as is will break it. Any ideas?
Update: here's what I changed that initially brought about the issue
iOutputCols = 9 'this was changed to 9 from 8
ReDim Preserve sOutputCols(iOutputCols)
sOutputCols(0) = "Policy No"
sOutputCols(1) = "Client"
sOutputCols(2) = "Trans"
sOutputCols(3) = "Effective Date"
sOutputCols(4) = "ClosingRef"
sOutputCols(5) = "Gross"
sOutputCols(6) = "Comm"
sOutputCols(7) = "Net Due"
sOutputCols(8) = "Risk" 'this line was added
Making the change here, while originally causing the error, doesn't seem special - I did small changes like the above elsewhere in the code and in other modules, one time I even did something as testval = "test" and even that redundant line will produce the error. The most minimalistic way to cause it? Simply open it up, save it without changing anything, and on next use the error occurs.
The error occurs at this line, in a completely different code section which is part of a form:
If strErr <> "" Then MsgBox strErr, vbInformation + vbOKOnly, "Action Error"
Application.ScreenUpdating = True 'error occurs here, message box which shows me the error right above
End Sub
Update 2
Removing the error handling throws the error on this line
Case "> Send Next Period Reminder" 'error on line below
Call ReplaceText(wordApp, "[office_address]", Range("Address_" & Worksheets("UserParms").Range("F6").Value).Value) 'error this line
Call ReplaceText(wordApp, "[office_address2]", Range("Address2_" & Worksheets("UserParms").Range("F6").Value).Value)
'more of the same replacetexts below
For context, this is when an option is selected for "Send Next Period Reminder", which pulls a word .dot template from a static folder and populates it based on the data selected within the sheet (Hence the replace texts). This is in a different module and has never been touched before.
Try properly qualifying your Range method calls. You have lines like this:
Call ReplaceText(wordApp, "[office_address]", Range("Address_" & Worksheets("UserParms").Range("F6").Value).Value) 'error this line
Call ReplaceText(wordApp, "[office_address2]", Range("Address2_" & Worksheets("UserParms").Range("F6").Value).Value)
While it may not be obvious, there are cases, both environmental and code-based, where these unqualified uses of Range could fail. Change the references like Range("Address... to something like yourTargetWS.Range("Address...

SPSS Script from version 15 to version 20 in BASIC

The below script is written in 'Winwrap basic' which is almost identical to VBA.
I would like this script to work on SPSS 20, the script works fine on SPSS15 (by changing the file extension from STT to TLO as that is what the tablelook file was back then).
However, whenever I run this script in SPSS 20 the wwb processor crashes with a generic error message 'WWBProcessor has encountered a problem and needs to close. We are sorry for the inconvenience.'
The script is well commented, but the purpose of the script is to change the tablelook of every table in the output viewer window, by activating each table in turn and setting the table look to one specified by the user, rotating the inner column labels, closing the table and activating the next table.
The loop continues until every table has been set to the new tablelook and rotation.
Manually setting the rotation of a few hundred tables is arduous and very time consuming not to mention numbingly boring. This script used to perform this task in seconds back in version 15, but ever evolving needs and lack of support for the older version has meant that I've been forced to use the newer version.
I'd be grateful for any assistance.
Mav
Option Explicit
Sub Main
'BEGIN DESCRIPTION
'This script changes all tabs to the same 'Tablelook' style. You will be prompted to choose the tablelook file.
'END DESCRIPTION
'******************
'Old description
'This script assumes that objSpssApp ist the currently running
'SPSS-Application and assigns every existing Pivot Table
'in the Output Navigator a new TableLook which can be selected
'from a Dialog box. Hidden tables will also be affected.
'Originally Created by SPSS Germany. Author: Arnd Winter.
'******************
'This script is written in the BASIC revision 'WinWrap Basic' code copied from VB or other basic languages may have to be modified to function properly.
On Error GoTo Bye
' Variable Declaration
' For an undertermined reason scripts cannot be executed throught the Utilites -> Run scripts menu,
' Instead they must be opened like a syntax file and ran from the SPSS 19 Scripting page.
' Functionality on SPSS 20 is now completely gone, error message only reads 'WWB processor has encountered a problem and needs to close'.
Dim objOutputDoc As ISpssOutputDoc 'Declares the Output variable
Set objOutputDoc = objSpssApp.GetDesignatedOutputDoc 'Assigns currently active output to Output variable
Dim strAppPath As String
Dim objOutputItems As ISpssItems 'variable defining every item in the current output window
Dim objOutputItem As ISpssItem 'variable defining the current item
Dim objPivotTable As PivotTable
Dim intCount As Integer 'declare the variable that will store the number of instances
Dim varStrLook As String
Set objOutputItems=objOutputDoc.Items
Dim i As Integer 'for loops we need an INT variable that will be counted against the number of instances 'i' is standard notation
' Find out SPSS Directory
strAppPath = objSpssApp.GetSPSSPath
' Select TableLook
'The Parametres you must enter into the GetFilePath() function are as follows:
'(Optional)Firstly you enter the initial file name (if none is required use an asterisk * and the file extention, or *.*)
'(Optional)The second part is the file extention expected, you can choose multiple filetypes if you seperate them with a semi-colon ;
'(Optional)The third parametre is the directory where the file should be opened.(default - Current path)
'The fourth parametre is the Title of the prompt, which should be enclosed in speech marks.
'The Final parametre is the 'Option'
'0 Only allow the user to select a file that exists.
'1 Confirm creation when the user selects a file that does not exist.
'2 Allow the user to select any file whether it exists or not.
'3 Confirm overwrite when the user selects a file that exists.
'+4 Selecting a different directory changes the application's current directory.
'For more detailed information visit the WWB website.
' http://www.winwrap.com/web/basic/language/?p=doc_getfilepath__func.htm
varStrLook = GetFilePath$("*.stt","stt",strAppPath,"Select Tablelook and confirm with Save.",4)
' Tested re-applying the dollar sign, cofusingly removing or adding the Dollar sign ($)
' seems to have no effect.
' If user presses Cancel or selected a file with the wrong file type then exit script
If (Len(varStrLook)= 0) Or (Right(varStrLook,3)<>"stt") Then
Exit Sub
End If
' Loop which assigns a new TableLook to all existing Tables.
intCount = objOutputItems.Count 'Assigns the total number of output items to the count-marker
For i = 0 To intCount-1 'Start loop
Set objOutputItem=objOutputItems.GetItem(i) 'Get current item
If objOutputItem.SPSSType=SPSSPivot Then 'If the item is a pivot table then...
Set objPivotTable=objOutputItem.ActivateTable 'Activate the table for editing
objPivotTable.TableLook = varStrLook 'Apply the earlier selected table look.
objPivotTable.RotateColumnLabels=True 'Rotate collumn lables
objOutputItem.Deactivate 'Confirm changes and deactivate the table
End If
Next 'End loop
'********************************************************
'Updated script from Version 15 ->
'Script now includes inner column label rotation
'Script has been modified and adapted to improve performance
'and to help people who wish to use/adapt the script
'in future endeavours.
'********************************************************
Bye:
End Sub
The first thing to try is to replace the activate/deactivate calls with
GetTableOLEObject
This is much more efficient and does not require the pivot table editor, but you can do all the things that you could do on an activated table.
If you don't have the current fixpack for V20, fixpack2, installing that would be a good idea, too.