
Determinar si un nombre de archivo es válido
Es bastante común en las aplicaciones permitir al usuario especificar una ruta y/o nombre de archivo para guardar archivos.
Como tal, una buena práctica sería validar la entrada del usuario antes de usarla a ciegas y quizás obtener errores y hacer que nuestras aplicaciones se bloqueen.
Por eso pensé en compartir rápidamente una forma posible de abordar esto.
Lo primero que hay que tener en cuenta es que Microsoft Windows tiene reglas que definen lo que no está permitido en los nombres de archivos y rutas. Estas reglas se detallan en:


Pero lo más destacado de las reglas es:
Un nombre de archivo no puede incluir
- < > : ” / \ | ? *
- Caracteres ASCII del 0 al 31
Además, el nombre en sí no debe ser una de las siguientes palabras reservadas:
- CON,PRN,AUX,NULO,COM0,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8,COM9,COM¹,COM²,COM³,LPT0,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8,LPT9,LPT¹,LPT²,LPT³
Hay un par de cosas más que debemos evitar, pero estos son los aspectos más comunes a respetar.
Ahora bien, hay una variedad de formas de abordar esto, podríamos:
- Utilice alguna API de archivo y pase el nombre y, si hay un error, sabremos que no es válido.
- Construir y utilizar RegEx
- Utilice VBA simple para validar la cadena
¿El nombre del archivo es válido o no? Verdadero o falso
Para el debate de hoy, elegí el segundo enfoque. Por ello, a continuación se muestra una función de ejemplo que validará si el nombre de archivo ingresado es aceptable según las reglas anteriores.
'---------------------------------------------------------------------------------------
' Procedure : Filename_IsValid
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website :
' Purpose : Determine is the proposed filename is valid or not based on Windows
' naming requirements
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
' (CC BY-SA 4.0) -
' Req'd Refs: None required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sFileName : Filename to validate (including extension)
'
' Usage:
' ~~~~~~
' ? Filename_IsValid("VBA Samples and Explanations.docx")
' Returns -> True
'
' ? Filename_IsValid("VBA Samples >>> Explanations.docx")
' Returns -> False
'
' ? Filename_IsValid("COM3.docx")
' Returns -> False
'
' Revision History:
' Rev Date(yyyy-mm-dd) Description
' **************************************************************************************
' 1 2024-03-25 Public Release
' 2 2024-03-28 Filename ending with '..' or ' '
'---------------------------------------------------------------------------------------
Public Function Filename_IsValid(sFilename As String) As Boolean
On Error GoTo Error_Handler
Dim iCounter As Long
Dim aChars() As String
Dim aNames() As String
Dim sFilenameWOExt As String 'Filename without extension
Dim IsValidFilename As Boolean
Const sIllegalChrs = ",:,"",/,\,|,?,*"
Const sIllegalNames = "CON,PRN,AUX,NUL,COM0,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8" & _
",COM9,COM¹,COM²,COM³,LPT0,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7" & _
",LPT8,LPT9,LPT¹,LPT²,LPT³"
'illegal characters
aChars = Split(sIllegalChrs, ",")
For iCounter = 0 To UBound(aChars)
If InStr(sFilename, aChars(iCounter)) > 0 Then
IsValidFilename = True
GoTo ReturnValue
End If
Next iCounter
'Ascii 0 through 31
For iCounter = 0 To 31
If InStr(sFilename, Chr(iCounter)) > 0 Then
IsValidFilename = True
GoTo ReturnValue
End If
Next iCounter
'Illegal names
If InStr(sFilename, ".") > 0 Then
sFilenameWOExt = Left(sFilename, InStrRev(sFilename, ".") - 1)
Else
sFilenameWOExt = sFilename 'No Extension
End If
aNames = Split(sIllegalNames, ",")
For iCounter = 0 To UBound(aNames)
If sFilenameWOExt = aNames(iCounter) Then
IsValidFilename = True
GoTo ReturnValue
End If
Next iCounter
'End with '..' or ' '
If Right(sFilename, 2) = ".." Or _
Right(sFilename, 2) = " " Then IsValidFilename = True
ReturnValue:
Filename_IsValid = Not IsValidFilename
Error_Handler_Exit:
On Error Resume Next
Exit Function
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Source: Filename_IsValid" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Function
Y ahí lo tienes, una función simple que puede validar si una cadena/nombre de archivo es aceptable o no.
Public Sub test()
Dim sFile As String
sFile = "SomeProposedFile*Name.xlsx"
If Filename_IsValid(sFile) Then
'All good, save as
Else
'The name is not acceptable, now what?! MsgBox
Debug.Print "Uh-oh"
End If
End Sub
y si ejecutamos este sub, obtendremos el resultado en la ventana Inmediata:
Uh-oh
(porque hay un * en el nombre del archivo y ese es uno de los caracteres ilegales)
¡Más información por favor!
Lo anterior devuelve simplemente Verdadero/Falso, pero en algunos casos queremos detalles para que el usuario conozca el problema exacto para que pueda corregirlo y volver a enviar el nombre. Por lo tanto, podríamos personalizar aún más la función anterior y obtener:
'---------------------------------------------------------------------------------------
' Procedure : Filename_IsValid2
' Author : Daniel Pineault, CARDA Consultants Inc.
' Website :
' Purpose : Determine is the proposed filename is valid or not based on Windows
' naming requirements
' Copyright : The following is release as Attribution-ShareAlike 4.0 International
' (CC BY-SA 4.0) -
' Req'd Refs: None required
'
' Input Variables:
' ~~~~~~~~~~~~~~~~
' sFileName : Filename to validate (including extension)
' sProblem : Variable that returns the exact nature of the file name error
'
' Usage:
' ~~~~~~
' ? Filename_IsValid2("VBA Samples and Explanations.docx", sFileNameError)
' Returns -> True, sFileNameError -> ''
'
' ? Filename_IsValid2("VBA Samples >>> Explanations.docx", sFileNameError)
' Returns -> False, sFileNameError -> 'Invalid Characters '>''
'
' ? Filename_IsValid2("COM3.docx", sFileNameError)
' Returns -> False, sFileNameError -> 'Invalid Name 'COM3''
'
' Revision History:
' Rev Date(yyyy-mm-dd) Description
' **************************************************************************************
' 1 2024-03-25 Public Release
' 2 2024-03-28 Filename ending with '..' or ' '
'---------------------------------------------------------------------------------------
Public Function Filename_IsValid2(sFilename As String, _
ByRef sProblem As String) As Boolean
On Error GoTo Error_Handler
Dim iCounter As Long
Dim aChars() As String
Dim aNames() As String
Dim sFilenameWOExt As String 'Filename without extension
Dim IsValidFilename As Boolean
Const sIllegalChrs = ",:,"",/,\,|,?,*"
Const sIllegalNames = "CON,PRN,AUX,NUL,COM0,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8" & _
",COM9,COM¹,COM²,COM³,LPT0,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7" & _
",LPT8,LPT9,LPT¹,LPT²,LPT³"
'illegal characters
aChars = Split(sIllegalChrs, ",")
For iCounter = 0 To UBound(aChars)
If InStr(sFilename, aChars(iCounter)) > 0 Then
IsValidFilename = True
sProblem = "Invalid Characters '" & aChars(iCounter) & "'"
GoTo ReturnValue
End If
Next iCounter
'Ascii 0 through 31
For iCounter = 0 To 31
If InStr(sFilename, Chr(iCounter)) > 0 Then
IsValidFilename = True
sProblem = "Invalid ASCII Characters '" & iCounter & "'"
GoTo ReturnValue
End If
Next iCounter
'Illegal names
If InStr(sFilename, ".") > 0 Then
sFilenameWOExt = Left(sFilename, InStrRev(sFilename, ".") - 1)
Else
sFilenameWOExt = sFilename 'No Extension
End If
aNames = Split(sIllegalNames, ",")
For iCounter = 0 To UBound(aNames)
If sFilenameWOExt = aNames(iCounter) Then
IsValidFilename = True
sProblem = "Invalid Name '" & sFilenameWOExt & "'"
GoTo ReturnValue
End If
Next iCounter
'End with '..' or ' '
If Right(sFilename, 2) = ".." Then
IsValidFilename = True
sProblem = "Cannot end a file name with '..'"
GoTo ReturnValue
End If
If Right(sFilename, 2) = " " Then
IsValidFilename = True
sProblem = "Cannot end a file name with ' '"
GoTo ReturnValue
End If
ReturnValue:
Filename_IsValid2 = Not IsValidFilename
Error_Handler_Exit:
On Error Resume Next
Exit Function
Error_Handler:
MsgBox "The following error has occurred" & vbCrLf & vbCrLf & _
"Error Source: Filename_IsValid2" & vbCrLf & _
"Error Number: " & Err.Number & vbCrLf & _
"Error Description: " & Err.Description & _
Switch(Erl = 0, "", Erl 0, vbCrLf & "Line No: " & Erl) _
, vbOKOnly + vbCritical, "An Error has Occurred!"
Resume Error_Handler_Exit
End Function
Public Sub test()
Dim sFile As String
Dim sFileNameError As String
sFile = "COM3.docx"
If Filename_IsValid2(sFile, sFileNameError) Then
'All good, save as
Debug.Print "'" & sFileNameError & "'"
Else
'The name is not acceptable, now what?! MsgBox
Debug.Print "'" & sFileNameError & "'"
End If
End Sub
y en el caso anterior obtendríamos una salida en la ventana inmediata de:
'Invalid Name 'COM3''
¡Convenio de denominación!
Tal vez el mejor enfoque, en lugar de permitir a los usuarios tener total libertad para nombrar los archivos, sería diseñar y codificar una Convención de Nomenclatura de Archivos (FNC, por sus siglas en inglés). Esto estandariza los nombres de los archivos, los hace más fáciles de descifrar, simplifica la clasificación y puede evitar todo el problema de tener nombres de archivos potencialmente inválidos.
Normalmente en una FNC podemos ver:
- Fecha
- Categoría/Tema
- Nombre
- Revisión
20240313_Ingeniería_RFC_V12RevA.docx
El objetivo debe ser proporcionar un nombre que proporcione la mayor cantidad de información posible en el nombre más corto posible. No debe crear nombres de archivo que ocupen entre 100 y 150 caracteres.
Incluso Harvard lo recomienda:


Luego, dicho formato podría incorporarse fácilmente a un formulario con diversas opciones elegidas por los usuarios y el nombre del archivo podría generarse automáticamente en función de esas opciones.
En mi carrera, también he estado expuesto a convenciones de nombres alfanuméricos, como:
095ATP45_2.1.doc
donde el nombre en sí puede descomponerse en componentes como:
- 095 -> RRHH
- ATP -> Manual de usuario para nuevos empleados
- 45 -> James Carleson
- 2.1 -> Número de revisión
Este no es un buen enfoque, ya que requiere que uno siempre tenga en cuenta la convención de nomenclatura corporativa para descifrar lo que realmente es el documento. ¡Las cosas deberían entenderse fácilmente con solo mirar el nombre!