Forum Discussion
Send data directly from COM3 to Excel
Hello Sir
Thank you for your help with this problem.
Unfortunately, I am running as 64-bit system, so it requires DECLARE PTRSAFE.
I edited the macro, and then I saw a blue ring spinning endlessly. No key worked, so I had to crash Excel.
Perhaps one of the other words requires an update.
Thank you
Jay Jacob Wind
For 64-bit systems, you need to update the VBA declarations to use PtrSafe and adjust some data types to be compatible with 64-bit VBA. Here is an updated version of the code, which includes the necessary changes for a 64-bit system:
Step 1: Set Up VBA in Excel
- Open Excel:
- Open a new or existing workbook where you want to log the data.
- Open the VBA Editor:
- Press Alt + F11 to open the VBA editor.
- Insert a New Module:
- In the VBA editor, go to Insert > Module to create a new module.
Step 2: Add VBA Code for Serial Communication
- Define API Functions:
- Add the following code to the new module to define the necessary Windows API functions:
Vba Code is untested backup your file.
Declare PtrSafe Function CreateFile Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As LongPtr
Declare PtrSafe Function ReadFile Lib "kernel32" (ByVal hFile As LongPtr, ByVal lpBuffer As String, ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Declare PtrSafe Function WriteFile Lib "kernel32" (ByVal hFile As LongPtr, ByVal lpBuffer As String, ByVal nNumberOfBytesToWrite As Long, ByRef lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Any) As Long
Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As Long
Declare PtrSafe Function GetLastError Lib "kernel32" () As Long
Const GENERIC_READ As Long = &H80000000
Const GENERIC_WRITE As Long = &H40000000
Const OPEN_EXISTING As Long = 3
Const FILE_ATTRIBUTE_NORMAL As Long = &H80
Const INVALID_HANDLE_VALUE As LongPtr = -1
2. Create Functions to Open, Read from, and Close the Serial Port:
- Add the following functions to handle the serial port communication:
vba Code
Dim hComm As LongPtr
Function OpenSerialPort(portName As String) As Boolean
hComm = CreateFile(portName, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)
If hComm = INVALID_HANDLE_VALUE Then
OpenSerialPort = False
Else
OpenSerialPort = True
End If
End Function
Function ReadSerialPort() As String
Dim buffer As String * 1024
Dim bytesRead As Long
Dim result As Long
result = ReadFile(hComm, buffer, Len(buffer), bytesRead, ByVal 0&)
If result <> 0 Then
ReadSerialPort = Left(buffer, bytesRead)
Else
ReadSerialPort = ""
End If
End Function
Function CloseSerialPort() As Boolean
CloseHandle hComm
CloseSerialPort = True
End Function3. Write the Main Subroutine to Read Data and Log to Excel:
- Add a subroutine to open the serial port, read data, and write it to the worksheet:
Vba Code
Sub ReadFromSerialPort()
Dim data As String
Dim row As Long
' Open the serial port
If Not OpenSerialPort("COM3") Then
MsgBox "Failed to open COM3"
Exit Sub
End If
' Set the initial row for logging data
row = 2 ' Assuming row 1 is for headers
' Loop to continuously read data
Do
data = ReadSerialPort()
If data <> "" Then
' Write data to the worksheet
ThisWorkbook.Sheets(1).Cells(row, 1).Value = Now
ThisWorkbook.Sheets(1).Cells(row, 2).Value = data
row = row + 1
End If
' Check for user interrupt (e.g., pressing Esc)
DoEvents
Loop Until False
' Close the serial port
CloseSerialPort
End Sub
Step 3: Add a Button to Run the Macro
- Go back to Excel.
- Go to Developer > Insert > Button (Form Control).
- Draw the button on the worksheet.
- Assign the ReadFromSerialPort macro to the button.
Usage
- Click the Button:
- Click the button you added to start reading data from the serial port.
- Data Logging:
- The macro will continuously read data from the serial port and log it to the worksheet, along with a timestamp.
Summary
This VBA script, updated for 64-bit systems, allows you to read data from a serial port (COM3) and log it directly into an Excel worksheet. The provided code sets up serial communication using Windows API functions and logs incoming data to an Excel worksheet. Be sure to back up your file before testing the code to avoid data loss.
If that doesn't help you, I would recommend using third-party software.
- jaywindJul 25, 2024Copper Contributor
I tried the 64-bit VBA, I really did.
When I run it, my computer hangs forever in a blue spinning loop, and I have to crash Excel with Task Manager. I can't even take a screenshot of the page, because it freezes my PrtScn button.
Any ideas?
- NikolinoDEApr 26, 2026Platinum Contributor
I’m sorry you’re dealing with that freezing issue—that "blue spinning loop" is a classic sign of a tight loop consuming all CPU resources or a blocking API call.
To give you a fix that actually works, I really need a bit more information from you:
- OS & Excel: (e.g., Windows 11 + Excel 365 64-bit)
- Device: What is connected to COM3? (Make/Model helps find the correct Baud Rate).
- Settings: What Baud Rate, Data Bits, Parity, and Stop bits does the device use? (Check the device manual or Device Manager > Port Settings > Advanced).
- Location: Is the file on a local drive or Network/OneDrive? (Network latency can exacerbate freezing).
However, I can try to tell you why it's hanging right now and how to stop it:
Culprit 1: The "Busy Wait" Loop
The current code uses DoEvents without a pause. This spins the CPU at 100%.- Fix: Add a micro-sleep. Replace DoEvents with:
DoEvents
Sleep 50 ' Requires declaring the Sleep API (see below)
Culprit 2: Missing COM Port Configuration (Most Likely)
The code opens COM3 but doesn't tell Windows how to talk to it (Baud rate, etc.). If the device is set to 9600 baud and Windows defaults to a different speed, data is garbage or empty, and the read loop never exits.- Fix: We must add SetCommState and SetCommTimeouts API calls to configure the port immediately after opening it.
Culprit 3: Blocking ReadFile
The ReadFile call is "blocking." If the device doesn't send data instantly, Excel freezes waiting for it.- Fix: We must set a Read Timeout (e.g., 100ms) using SetCommTimeouts. If no data arrives in 100ms, the function returns, and the loop tries again without crashing.
Immediate "Safe" Code Snippet (64-bit compatible with Timeouts):
Since you are crashing, try this minimal version. It includes the Sleep API to prevent freezing and basic error handling.
' Add this at the very top of the module Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) ' ... [Keep your existing Declarations for CreateFile, ReadFile, etc.] ... ' Add Timeout Structures and APIs Type COMMTIMEOUTS ReadIntervalTimeout As Long ReadTotalTimeoutMultiplier As Long ReadTotalTimeoutConstant As Long WriteTotalTimeoutMultiplier As Long WriteTotalTimeoutConstant As Long End Type Declare PtrSafe Function SetCommTimeouts Lib "kernel32" (ByVal hFile As LongPtr, ByVal lpCommTimeouts As LongPtr) As Long Declare PtrSafe Function GetCommTimeouts Lib "kernel32" (ByVal hFile As LongPtr, ByVal lpCommTimeouts As LongPtr) As Long ' Modified Open Function with Timeouts Function OpenSerialPort(portName As String) As Boolean hComm = CreateFile(portName, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0) If hComm = INVALID_HANDLE_VALUE Then OpenSerialPort = False Exit Function End If ' SET TIMEOUTS (Crucial for preventing hangs) Dim timeouts As COMMTIMEOUTS timeouts.ReadIntervalTimeout = 0 timeouts.ReadTotalTimeoutMultiplier = 0 timeouts.ReadTotalTimeoutConstant = 100 ' 100ms read timeout SetCommTimeouts hComm, timeouts OpenSerialPort = True End Function ' Modified Read Function Function ReadSerialPort() As String Dim buffer As String * 1024 Dim bytesRead As Long Dim result As Long ' Non-blocking check approach is complex, so we rely on the timeout set above result = ReadFile(hComm, buffer, Len(buffer), bytesRead, ByVal 0&) If result <> 0 And bytesRead > 0 Then ReadSerialPort = Left(buffer, bytesRead) Else ReadSerialPort = "" ' Timeout or empty End If End Function ' Modified Loop Sub ReadFromSerialPort() Dim data As String Dim row As Long If Not OpenSerialPort("COM3") Then MsgBox "Failed to open COM3. Check Device Manager." Exit Sub End If row = 2 Do data = ReadSerialPort() If data <> "" Then ThisWorkbook.Sheets(1).Cells(row, 1).Value = Now ThisWorkbook.Sheets(1).Cells(row, 2).Value = data row = row + 1 End If ' PREVENT FREEZE: Yield CPU and Sleep DoEvents Sleep 50 ' 50ms pause ' Optional: Check if Esc key is pressed to stop If GetAsyncKeyState(vbKeyEscape) Then Exit Do Loop CloseSerialPort End SubIf you share the device details/settings requested above, I can provide the full SetCommState (Baud rate) code as well.
In the meantime, I strongly recommend downloading PuTTY, selecting "Serial," entering COM3 and the correct Baud Rate, and seeing if text appears. If it doesn't appear in PuTTY, the issue is drivers/cables, not Excel.
I hope this information is helpful to you.