VBA API Call returns value when run on one computer but not on another identical one - api

I have an API call that returns a value from a foreign listview (Java application) that works just fine on my computer. When I try to run the same call on my colleague's computer, however, it just returns "0". We work in an office and our computers are identical--same model, same version of Windows, same version of MS Office (with Excel). The file with the API call resides on a shared network location, so it is the exact same file, exact same code that I am running on both machines. I am not very well-versed in API, so I'm probably missing something simple, but I haven't been able to solve it. Can anyone clue me in to why the code works on one machine but not the other?
Here's the code with the call--see my NOTE about halfway down that shows where I get a discrepancy:
Public Function GetListviewItem(ByVal hWindow, pRow) As String
Dim result As Long
Dim myItem As LV_ITEM
Dim pHandle As Long
Dim pStrBufferMemory As Long
Dim pMyItemMemory As Long
Dim strBuffer() As Byte
Dim index As Long
Dim tmpstring As String
Dim strLength As Long
Dim pColumn As Long
Dim lProcID As Long
'**********************
'init the string buffer
'**********************
ReDim strBuffer(MAX_LVMSTRING)
pColumn = 2
'***********************************************************
'open a handle to the process and allocate the string buffer
'***********************************************************
GetWindowThreadProcessId hWindow, lProcID ' Get the process ID in which the ListView is running
If lProcID <> 0 Then
pHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, lProcID)
pStrBufferMemory = VirtualAllocEx(pHandle, 0, MAX_LVMSTRING, MEM_COMMIT, PAGE_READWRITE)
'************************************************************************************
'initialize the local LV_ITEM structure
'The myItem.iSubItem member is set to the index of the column that is being retrieved
'************************************************************************************
myItem.mask = LVIF_TEXT
myItem.iItem = pRow
myItem.iSubitem = pColumn
myItem.pszText = pStrBufferMemory
myItem.cchTextMax = MAX_LVMSTRING
'**********************************************************
'write the structure into the remote process's memory space
'**********************************************************
pMyItemMemory = VirtualAllocEx(pHandle, 0, Len(myItem), MEM_COMMIT, PAGE_READWRITE)
result = WriteProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), 0)
'*************************************************************
'send the get the item message and write back the memory space
'*************************************************************
'NOTE: THE 'result' VARIABLE IS WHERE I GET VALUES, BUT THE OTHER COMPUTER GETS '0'
result = SendMessage(hWindow, LVM_GETITEMTEXTA, pRow, ByVal pMyItemMemory)
result = ReadProcessMemory(pHandle, pStrBufferMemory, strBuffer(0), MAX_LVMSTRING, 0)
result = ReadProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), 0)
'**************************************************
'turn the byte array into a string and send it back
'**************************************************
For index = LBound(strBuffer) To UBound(strBuffer)
If Chr(strBuffer(index)) = vbNullChar Then Exit For
tmpstring = tmpstring & Chr(strBuffer(index))
Next index
tmpstring = Trim(tmpstring)
'***********************************************
'deallocate the memory and close the process handle
'**************************************************
result = VirtualFreeEx(pHandle, pStrBufferMemory, 0, MEM_RELEASE)
result = VirtualFreeEx(pHandle, pMyItemMemory, 0, MEM_RELEASE)
result = CloseHandle(pHandle)
If Len(tmpstring) > 0 Then GetListviewItem = tmpstring
End If
End Function
Thanks to anyone who might have some suggestions.

Related

Combine 2 pdfs in one using VBA

I'm currently working on a macro that creates a PDF from a SolidWorks file and then, if the Solidworks File is an assembly, it would merge the pdf with its BOM.
The problem is that I've coded the merge part of the macro, but I keep getting a "False" result on the merge line of my code and I can't find why...
Once it will be debugged, this will become a Function that will get 2 file paths to merge.
Can you help me make the macro actually merge the two files? I can't find anything about why it can return a false results.
So thank you for your help!
Here's my actual code:
Sub CombinePDFs() '(ByVal NewAsmPdf As String, ByVal OldAsmPdf As String)
' The function will combine the PDFs keeping the BOM of the older file merged (The one which is replaced)
Dim Adobe As AcroPDDoc
Dim PDF1 As Object
Dim PDF2 As Object
Dim PageNF As Long
Dim PageOF As Long
Dim b As Byte
Dim NewAsmPdf As String
Dim OldAsmPdf As String
NewAsmPdf = "Path.PDF"
OldAsmPdf = "Path_BOM.PDF"
' Defines the two PDFs to be merged
Set PDF1 = CreateObject("AcroExch.PDDoc")
PDF1.Open (NewAsmPdf)
Set PDF2 = CreateObject("AcroExch.PDDoc")
PDF2.Open (OldAsmPdf)
'Get the pages to be keep
PageNF = PDF1.GetNumPages
PageOF = PDF2.GetNumPages - PageNF
'Insert PDF2 BOM in PDF1
If PDF1.InsertPages(PageNF, PDF2, PageNF + 1, PageOF, 0) Then 'Here is my problem : Keep having false (No merge)
Kill (OldAsmPdf)
Else
MsgBox ("Could not merge the Old and New file")
End If
End Sub
SOLVED!
I found out that VBA counts from 0 (So page 1 is actually the page 0) so the false was returned due to impossible values in attributes.
Here's the code of the function that I've done:
Function CombinePDFs(ByVal NewAsmPdf As String, ByVal OldAsmPdf As String)
' The function will combine the 2 PDFs and replace the OldFile by the NewFile
Dim PDF1 As Object
Dim PDF2 As Object
Dim PageNF As Long
Dim PageOF As Long
Dim NewAsmPdf As String
Dim OldAsmPdf As String
' Defines the two PDFs to be merged
Set PDF1 = CreateObject("AcroExch.PDDoc")
PDF1.Open (NewAsmPdf)
Set PDF2 = CreateObject("AcroExch.PDDoc")
PDF2.Open (OldAsmPdf)
'Get the pages to be keep
PageNF = PDF1.GetNumPages
PageOF = PDF2.GetNumPages
' Insert PDF2 BOM in PDF1
If PDF1.InsertPages(PageNF - 1, PDF2, PageNF, PageOF-1, 0)
If Not PDF1.Save(PDSaveFill, NewAsmPdf) Then
MsgBox ("Not saved")
End If
' Delete "_BOM.PDF" file
PDF2.Close
Kill (OldAsmPdf)
Else
MsgBox ("Could not merge the Old and New file")
End If
' Clear memory
Set PDF1 = Nothing
Set PDF2 = Nothing
End Function
Have fun!

Visual Basic CInt error

I am trying to make a function that looks at an image, and return the X pixel value.
When i run the code, it throws an error on the Int1=CInt(Xdim) line, saying "Type Mismatch (10080)"
If i hard-code the value i am testing into Xdim, it works fine.
Function ImgXDim(filename As String) As Integer ' Finds the X dimension in pixels of a loaded image
Dim objShell As Object
Dim objFolder As Object
Dim objFile As Object
Dim ImgSize As String
Dim Int1 As Integer
Dim Xdim As String
Dim strarray() As String
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.NameSpace(MacroDir & "\PICS\")
Set objFile = objFolder.ParseName(filename)
ImgSize = objFile.ExtendedProperty("Dimensions") ' Returns string of "700 x 923"
strarray = Split(ImgSize, " x ") ' Split into 2 strings of "700" and "923"
Xdim = CStr(strarray(0)) ' Force Xdim to be a string of "700"
Int1 = CInt(Xdim) ' Convert Xdim to an integer
ImgXDim = Int1 ' Return Integer
End Function
First check if value can be converted to an integer:
If IsNumeric(Trim(Xdim)) then
Int1 = CInt(Xdim)
else
'for debug purposes
MsgBox ("XDim non-numeric or empty")
End If
Ok, i couldnt find what character was causing the issue, so i used this loop of code to pull out only numbers, and it seems to work.
For X = 1 To Len(Xdim)
If IsNumeric(Mid(Xdim, X, 1)) = True Then
holder = holder & Mid(Xdim, X, 1)
End If
Next X
Here the WIA version:
Function ImgXDim(filename As String) As Long
Dim imgWIA as New WIA.ImageFile 'Early Binding needs a reference to Windows Image Aquisition Library in VBA-Ide->Tools->References
'Dim imgWIA as Object 'Late Bound Version
'Set imgWIA = CreateObject("WIA.ImageFile")
imgWIA.LoadFile MacroDir & "\PICS\" & filename
ImgXDim = imgWIA.Width ' use .Height for height
End Function
As you see, just three lines of code and returns a long, not a string that needs parsing.
Useful functions for resize, rotate and more.
Also useful if you want to display Tiffs in a picture control (page by page) and more.

Debugging in autocad VBA ide is not displaying where the error is

Whenever i am trying to debug or run the program and if it encounters error, the VBE (Autocad) doesn't display the line where the error is, unlike in other IDEs, it used to come at that line and highlight with yellow color. Also, the scroll doesn't work. I know i should install plugins but i am unable to help myself.
Option Explicit
Sub Test()
'Declarations
'Opened Document
Dim acDocu As AcadDocument
Set acDocu = ThisDrawing.Application.ActiveDocument
'Select on screen
Dim acSelectionSet As AcadSelectionSet
Set acSelectionSet = ThisDrawing.SelectionSets.Add("SjjEffffT")
acSelectionSet.SelectOnScreen
'Manipulating in loops for finding group names having objects selected
Dim entity As AcadEntity
Dim entityhandle() As String
Dim Grp As AcadGroup
Dim groupname() As String
Dim i As Integer
i = 0
Dim j As Integer
j = 0
Dim temp As Integer
temp = 0
Dim GrpEnt As AcadEntity
Dim grpenthandle As String
Dim entity_count As Integer
'Dim entity_array As Variant
entity_count = acSelectionSet.Count
ReDim entityhandle(entity_count)
ReDim groupname(entity_count)
For Each entity In acSelectionSet
'entity_array = entity
entityhandle(i) = entity.Handle
For Each Grp In ThisDrawing.groups
For Each GrpEnt In Grp
grpenthandle = GrpEnt.Handle
If entityhandle(i) = grpenthandle Then
If temp = 0 Then
groupname(j) = Grp.Name
Debug.Print "Group in selection:" & groupname(j)
j = j + 1
End If
End If
temp = temp + 1
Next
temp = 0
Next
i = i + 1
Next
'Copying the objects and pasting into new drawing
Dim acDocto As AcadDocument
Dim file_name As String
'file_name = InputBox("Enter the file name along with full path and extension")
file_name = "D:\PI_Tool_files_3223\D00440023new.DWG"
Set acDocto = Documents.Open(file_name)
Dim acObject As AcadObject
Dim retvalue As Variant
retvalue = acDocu.CopyObjects(entityhandle, acDocto.ModelSpace)
acSelectionSet.Delete
End Sub
The code is written above. But i think the problem is with the add-in as i can't debug.
The VBA IDE is pretty old (1998) and it has limited debugging abilities. You should stop using this, it's an obsolete technology, not actively supported by Microsoft/Autodesk anymore.
For some errors, it is not able to locate the line where the error occurred, and you're left with obscure error codes and useless messages.
Have you tried setting a breakpoint at the first possible line? (Set acDocu = ThisDrawing.Application.ActiveDocument)
Then step through to see the offending object/property/method.
It doesn't always work.
Can you load the code into a module, instead of "ThisDrawing", then debug?

Small function to rearrange string array in VBA

I've been writing a macro for Solidworks in VBA, and at one point I'd like to rearrange the sheets in a drawing in the following way--if any of the sheets are named "CUT", bring that sheet to the front. Solidworks API provides a way to rearrange the sheets, but it requires an array of sheet names sorted into the correct order--fair enough. The way to get the sheet names looks to be this method.
So, I tried to write a small function to rearrange the sheets in the way I want. The function call I'm trying to use and the function are shown here
Function Call
Dim swApp As SldWorks.SldWorks
Dim swDrawing As SldWorks.DrawingDoc
Dim bool As Boolean
Set swApp = Application.SldWorks
Set swDrawing = swApp.ActiveDoc
.
.
.
bool = swDrawing.ReorderSheets(bringToFront(swDrawing.GetSheetNames, "CUT"))
Function Definition
Private Function bringToFront(inputArray() As String, _
stringToFind As String) As String()
Dim i As Integer
Dim j As Integer
Dim first As Integer
Dim last As Integer
Dim outputArray() As String
first = LBound(inputArray)
last = UBound(inputArray)
ReDim outputArray(first to last)
For i = first To last
If inputArray(i) = stringToFind Then
For j = first To (i - 1)
outputArray(j + 1) = inputArray(j)
Next j
For j = (i + 1) To last
outputArray(j) = inputArray(j)
Next j
outputArray(first) = stringToFind
End If
Next i
bringToFront = outputArray
End Function
The error I get is "Type mismatch: array or user defined type expected" on the function call line. I've done quite a bit of searching and I think what I'm messing up has to do with static vs dynamic arrays, but I haven't quite been able to get to the solution on my own.
Besides the corrections suggested in the comments, what is happening is that at the lines
bringToFront(j + 1) = inputArray(j)
and
bringToFront(first) = stringToFind
the compiler thinks you are trying to call recursively the function bringToFront. That is why it complains about the number of parameters in the error message. To fix this, just create another array as local array variable, with a different name, let us name it "ret", fill it appropriately, and assign it at the end before returning.
EDIT: Also, it is better to declare the arrays as Variant types to avoid interoperability problems between VB6 and .Net . This was the final issue
Private Function bringToFront(inputArray As Variant, _
stringToFind As String) As Variant
Dim i As Integer
Dim j As Integer
Dim first As Integer
Dim last As Integer
first = LBound(inputArray)
last = UBound(inputArray)
Dim ret() As String
ReDim ret(first To last)
For i = first To last
If inputArray(i) = stringToFind Then
For j = first To (i - 1)
ret(j + 1) = inputArray(j)
Next j
ret(first) = stringToFind
End If
Next i
bringToFront = ret
End Function

twain ocr function returns empty byte

i have the below code:
ddlResultFormat.Items.Add("Text")
dynamicDotNetTwain1.LoadImage("C:\Users\elj\Desktop\3b072e9b-76b4-4776-bd3c-5984074d8ecd.png")
Dim r = dynamicDotNetTwain1.GetImage(dynamicDotNetTwain1.CurrentImageIndexInBuffer).Width.ToString()
Dim l = dynamicDotNetTwain1.GetImage(dynamicDotNetTwain1.CurrentImageIndexInBuffer).Height.ToString()
Dim languageFolder As String
languageFolder = "C:\Program Files (x86)\Dynamsoft\Dynamic .NET TWAIN 5.2 Trial\Samples\Bin\"
Dim languages As New Dictionary(Of String, String)
languages.Add("English", "eng")
Me.dynamicDotNetTwain1.OCRTessDataPath = languageFolder
Me.dynamicDotNetTwain1.OCRLanguage = "English"
Dim ocrResultFormat As Dynamsoft.DotNet.TWAIN.OCR.ResultFormat
ocrResultFormat = CType(System.Enum.Parse(GetType(Dynamsoft.DotNet.TWAIN.OCR.ResultFormat), Val("&H" & 0)), Dynamsoft.DotNet.TWAIN.OCR.ResultFormat)
Me.dynamicDotNetTwain1.OCRResultFormat = ResultFormat.Text
Dim strDllPath As String
strDllPath = "C:\Program Files (x86)\Dynamsoft\Dynamic .NET TWAIN 5.2 Trial\Redistributable\OCRResources\"
dynamicDotNetTwain1.OCRDllPath = strDllPath
If (Me.dynamicDotNetTwain1.CurrentImageIndexInBuffer < 0) Then
Dim jajajja = "Please load an image before doing OCR!"
End If
Dim sbytes As Byte()
sbytes = Me.dynamicDotNetTwain1.OCR(Me.dynamicDotNetTwain1.CurrentSelectedImageIndicesInBuffer)
the problem that i'm facing is that the sbytes byte array is being always set to empty although the indice in the buffer is correct and the paths and the dll are well implemented but the convert to the byte array is not being successful i'm not getting any exception but the length of the byte is 0
any idea how can i fix this?
Please update the following line of code and try again.
Me.dynamicDotNetTwain1.OCRLanguage = "eng" 'not English