Forum Discussion
Send data directly from COM3 to Excel
For a simpler solution to send data from a device connected via a serial port (COM3) directly to Excel, you can use third-party software that bridges the serial port data to Excel. One such tool is Tera Term, a free terminal emulator that can log serial data to a file, combined with Excel's external data import feature. A other third-party software is PuTTY for Serial Communication.
Another approach would be using Python and extensive settings. Python allows you to fully customize the data collection and processing pipeline to fit your exact needs. You can control how data is read, parsed, processed, and written to Excel. But it requires programming knowledge and is more time-consuming to create than using third-party software.
An additional option would be VBA. VBA can handle communication with the serial port by leveraging Windows API functions.
Step-by-Step Guide Using VBA
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
1. 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 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 Long
Declare Function ReadFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As String, ByVal nNumberOfBytesToRead As Long, ByRef lpNumberOfBytesRead As Long, ByVal lpOverlapped As Any) As Long
Declare Function WriteFile Lib "kernel32" (ByVal hFile As Long, ByVal lpBuffer As String, ByVal nNumberOfBytesToWrite As Long, ByRef lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Any) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Declare 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 Long = -12. Create Functions to Open, Read from, and Close the Serial Port:
- Add the following functions to handle the serial port communication:
Vba Code is untested backup your file
Dim hComm As Long
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 is untested backup your file
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 Sub4. 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
Using VBA for this task allows you to stay within the Excel environment and avoid the need for third-party software or additional programming languages. The provided code sets up serial communication using Windows API functions and logs incoming data to an Excel worksheet. Adjust the COM port and baud rate settings as needed for your specific device.
The VBA Code edited with the help of AI.
My answers are voluntary and without guarantee!
Hope this will help you.
Was the answer useful? Mark as best response and like it!
This will help all forum participants.
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
- NikolinoDEJul 21, 2024Platinum Contributor
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 = -12. 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 SubStep 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.