Increase the power of ‘VisualNEO Win’ with Perl: report of an experiment

1. Introduction

How it came about, I don’t remember. But for a year now I have been working with Perl almost daily. Perl is a great language (see reiniermaliepaard.nl/perl for my journey). It’s convenient for an infinite set of programming problems. In addition, Perl can run on different platforms (for me Windows and Linux are relevant). I am so impressed by the many possibilities offered by Perl that I wondered if ‘VisualNeo Win’ could be extended using Perl. Let’s dig deeper.

2. Why Perl is a great language?

Let’s try to convince you:

  1. It’s stable and actively developed
  2. It’s very, very fast.
  3. It’s a language that is easily to understand (indeed, easy for ‘VisualNeo Win’ developers)
  4. It has a massive documentation, tutorials, books etc.
  5. It has more than 200.000 modules to invoke and to extend your Perl script (1). So why reinvent the wheel? In addition, most of the modules provide example code!
  6. It has a large community. And e.g. on reddit.com and stackoverflow.com many questions and answers on Perl programming problems can be found.
  7. The sympathetic concept: TIMTOWTDI (2), meaning “there is more then one way to do it” (in contrast to Python where there is only one way to do things).
  8. Regular expressions are Perl’s core business. This means that text processing is a very powerful feature.

Worth mentioning: Perl can embed Javascript code and vice versa, database applications with e.g. Oracle and mySQL can easily be made, popular libraries to handle XML, CSV are available and frameworks as Catalyst and Mojolicious can be used. To get some more ideas, study https://cpan.org and be impressed by the daily updates and new modules.

3. Practical example

Before studying technical aspects of the communication between ‘VisualNeo Win’ and Perl, let me indicate some advantages shortly.
An example among others of what is easily can be done in Perl: processing Excel files.

– create
– read (also fetching all rows and columns separately)
– update
– and a lot more…

Complex? No, what do you -after installing an Excel Module like Spreadsheet::Read- think of:

$cell_A1 = $excel->[1]{A1} 

to read the value of cell A1 ([1] refers to the first datasheet). And when reading data from an Excel file, you can easily apply e.g. statistical functions on the collected data (using a Statistics module like Statistics::Lite).

About writing and updating (using another module Excel::Writer::XLSX):

$excel->write("A2", "second row, cell 1") 

which is the same as

$excel->write(1, 0, "second row, cell 1") # zero based, so the 1 refers to the second row and the 0 to the first cell

now using coordinates.

$excel->write("A4", "=SUM(A1:A3)")

adding formulas.

More modifying operations? Add worksheets, color fields, align cells, add chart and shape, validate data etc. ‘VisualNeo Win’ can play a role in these reading and writing actions, as we’ll see soon.

4. How connect ‘VisualNeo Win’ into Perl and vice versa?

I believe that there are many answers to this question, I’m not aware of or I do not have the skills to implement an adequate solution, professionals would choose. So I thought about a basic solution:

communication between ‘VisualNeo Win’ and Perl via a shared text file
So a simple (you may say ‘rather primitive’ or something like that) file based and file shared approach. The concept:

1. Perl performs a task and writes the result to a file, e.g. output.txt
2. ‘VisualNeo Win’ reads the file output.txt and processes its contents.

Three roles for ‘VisualNeo Win’ have to mentioned:

3. it defines the Perl’s task, invoking Perl with the Run command
4. it does some filemanagement, e.g. cleaning the file output.txt and err.txt before a new task is performed
5. it shows error messages if something went wrong

5. Stress-test

I tested in a loop with 10.000 iterations: ‘VisualNeo Win’ wrote data to a file and Perl was simultaneously writing data to the same file. No problems found, ‘VisualNeo Win’ and Perl appear to be polite partners in the process.

6. How to invoke Perl?

After installing Strawberry Perl on Windows (3), Perl is in the PATH and you can invoke Perl with the ‘VisualNeo Win’ Run command. Example:

SetVar "[log]" "[PubDir]err.txt"
SetVar "[output]" "[PubDir]output.txt"
SetVar "[input]" "!0-10"
Run "cmd" "/c perl odd.pl [output] [input] 2>[log]" "Wait+Hidden" " " ""

Here, the Perl file ‘odd.pl’ is called with two arguments (the number of arguments is unlimited in Perl). The program ‘odd.pl’ calculates the odd numbers in the range 0-10 and writes the result to the outputfile (notice the magical ! to prevent evaluation; so the input variable has the literal string 0-10). The command 2>[log] means that Perl writes error messages to the file defined with the variable [log]: err.txt (which can be read by ‘VisualNeo Win’).

The Run command could be shorter with an extra redirection >[output] (of course, you’ve only to adapt odd.pl a bit because now only one argument), but the performance is not better:

Run “cmd” “/c perl odd.pl [input] >[output] 2>[log]” “Wait+Hidden” ” ” “”

So, I’ll stick with the first solution that has [output] as argument.

Notice that if your argument has spaces (e.g. in case of trim functions), then you’ve to use [#34].
So write SetVar “[input]” “[#34]    a  b   c [#34]” instead of SetVar “[input]” ”    a  b   c ”

Otherwise, Perl will parse the argument, using space as delimiter.

7. The template Perl file

I’ve made several Perl files that share a common design; in other words, the files are elaborations of a template. Here the ‘odd.pl’, slightly annotated:

use Set::IntSpan; # Step 1. invoke a module

$result = "Error!"; # Step 2. the default value of the return variable to make the code shorter

if (scalar(@ARGV) == 2) # Step 3. check if there are two arguments in the array @ARGV
{
  ($outputfile, $data) = @ARGV; # Step 4. assigns the array arguments to in this case two variables $outputfile and $data
  
  if($outputfile && $data) { # Step 5. extra check if arguments are defined; validation could be better of course
	
    $set = new Set::IntSpan $data; # Step 6. example code provided by the module
    @range = elements $set; # Step 7. # define range of numbers
    @odd = grep { $_ & 1 } @range ; # Step 8. filter the odd numbers
    $result = join(", ", @odd); # Step 9. make the string $result
  }

  if (open(FH, '>', $outputfile)) # Step 10. open outputfile
  {
    print(FH $result); # Step 11. write $result to the outputfile
    close(FH); # Step 12. close
  }
  else
  {
    # this code block should be not necessary	  
    # it shows an exceptional error:
    # 13. define a notepad call script, showing an error message (from a text file)
    $cmd = "cmd.exe /c notepad.exe error_opening_file.txt"; 
    system($cmd); 
  }
  
}

8. Composing your Perl file

Notice that in the previous code with its 13 steps

– Step 1 is variable: which module(s) to invoke?
– Step 4 is variable: what is the number of arguments?
– The code block of Step 6 till Step 9 is the only variable section of the Perl template. $result is the output variable (which has a default value: step 2).

So, your Perl file is easily made, modifying a few lines and one code block section (which can be from simple to complex). Another slightly annotated example. It determines all permutations of a semicolon separated string (like a;b;c)

use Algorithm::Permute;# invoke the relevant module

$result = "Error!";

if (scalar(@ARGV) == 2)
{
  ($outputfile, $data) = @ARGV;
  $p = Algorithm::Permute->new([split(";",$data)]);  # the string argument is split on the semicolon separator to create the necessary array.
  $str = $str . "\n" . join(", ", @res) while (@res = $p->next);  # append all permutations to variable $str
  $result = substr($str, 1) if ($str ne "");  # assign a value to the $result variable other than the default one  
}

if (open(FH, '>', $outputfile))
{
  print(FH $result);
  close(FH);
}

Don’t bother if this code is not completely clear to you (it’s from the module examples). My point is only that you can fill in the Perl template with minimal changes.

9. ‘VisualNeo Win’ code

The ‘VisualNeo Win’ code to invoke Perl is very simple, as shown previously. Try my visualneoperl.pub and study the Perl files and the communication with ‘ Visual Neo Win’. Notice Startup and Shutdown code, the subroutines and the code under the pushbuttons. That’s it. You can download the package https://reiniermaliepaard.nl/visualneoperl/visualneoperl.zip here. Notice that you’ve to install Perl and the relevant Modules (open the .pl files in Notepad and look at the use command) to run the application.

10. Performance

The communication process between ‘VisualNeo Win’ and Perl is very fast (tested on Lenovo X240 – Intel i5-4300U (5) @ 2.900GHz- under Windows 10 Professional). To demonstrate, I’ve made a small video with some statistical functions:

 

 

 

 

11. Is installing a module always necessary?

Some modules for your software problems are built in. That means that you don’t have to install a module via cpan. You can find them on https://perldoc.perl.org/modules. Examples are: Math::Trig provides many trigonometric functions or the module Win32 contains interfaces to some Win32 API Functions. Notice that you’ve still to include ‘use Math::Trig;’ or ‘use Win32;’ in your script.

Sometimes you don’t need a module at all, e.g. when processing data with regular expressions (although there are special Regex modules!).

12. What to do if a module is a wrapper?

Till now, I had no problems with installing Perl modules (5). However, I had difficulties with Image::OCR::Tesseract. It appears to be a wrapper for Tesseract-OCR, an optical character recognition engine. So you’ve to install Tesseract-OCR first:

  1. The Mannheim University Library (UB Mannheim) uses Tesseract to perform text recognition and provides a Window binary: https://github.com/UB-Mannheim/tesseract/wiki. It’s easy to install.
  2. Install the cpan module Image::OCR::Tesseract, which runs fine under Linux.
  3. Unfortunately, installing on Windows does not work. What to do?

Luckily, you can run Tesserac-OCR, invoking it with two arguments:

SetVar "[input]" "[PubDir]test.jpg"
.SetVar "[output]" "[PubDir]output_ocr.txt"
.Tesserac automaticaly adds the extension .txt
SetVar "[name_output_file]" "output_ocr"

Run "cmd" "/c C:\Tesseract-OCR\tesseract.exe [input] [name_output_file] 2>[log]" "Wait+Hidden" " " ""

And it works flawlessly (and fast). This was my image test.jpg:

test perl visualneoweb

and this was the extracted text from it, saved into output_ocr.txt:

Visually design and develop Windows Apps

It's easy to create and publish your own Windows software apps with VisualNEO for Windows.
Even inexperienced users can quickly combine combine text, pictures, sound, video, HTML content, Internet links, databases,
special effects and other elements to create interactive, professional software programs.

Of course, ‘VisualNeo Win’ can read output_ocr.txt and Perl can help you to modify the text as you want!

13. Deployment

  1. Installing Strawberry Perl is straightforward: run the recommended msi version (3). Then the user runs simply the ‘VisualNeo Win’ app as described previously. The cpan client, necessary to install modules, is default in Strawberry Perl (3).
  2. You can use Strawberry Perl Portable (4) with your ‘VisualNeo Win’ app…It should work without problems.

Option 1 is IMHO the best. It is the one I’ve worked with.

14. Conclusion

The experiment has for me a positive outcome (6). Perl files aka plugins! Instead of extending ‘VisualNeo Win’ with some specialized plugins, you could quite easily make specialized Perl files and increase in this way the power of ‘Visual Neo Win’ with all Perl offers. And that’s very impressive.

Thank you for reading!

Footnotes
(1) You may ask if these modules are of good quality. I can’t guarantee, but if often more than one developer is involved in creating the module (controlled by a community), I’ve no doubt…
(2) Which solution do you want? :-)
$concat = $a.$b
$concat = “$a$b”
$concat = join ”, $a, $b;
$concat = sprintf(“%s%s”,$a,$b);
$concat =~ s/.*/$a$b/s;
(3) Strawberry Perl on https://strawberryperl.com and use the recommended msi version.
After installing Perl, type ‘cpan’ at the command line and after the cpan prompt you can write ‘ install <Module>’ to install the module, you want. Example: install Statistics::Lite (and press Return). Notice that Perl is case-sensitive! The install instructions can be found in the Module description!
(4) https://strawberryperl.com provides also a portable version.
(5) Select the modules that are recently updated. And notice that there are often alternatives to a module.
(6) I feel no need to extend the experiment to other languages as Python or Lua, but I think it should work also.