Librería de Snippets para VB.NET !! (Compartan aquí sus snippets)
Eleкtro:
Convertir un objeto Datatable a una tabla en formato Markdown:
Código
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Converts the elements of a <see cref="DataTable"/> into a Markdown table.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example that shows how to convert a DataTable object to Markdown table.
''' <code language="VB.NET">
''' Dim dt As New DataTable()
''' dt.Columns.Add("ID", GetType(Integer))
''' dt.Columns.Add("Name", GetType(String))
''' dt.Rows.Add(1, "John")
''' dt.Rows.Add(2, "Doe")
'''
''' Dim markdownTable As String = EnumerableToMarkdownTable(dt)
''' Console.WriteLine(markdownTable.ToString())
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <param name="table">
''' The source <see cref="DataTable"/>.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A string representing the Markdown table.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Shared Function DataTableToMarkdownTable(table As DataTable) As String
If table Is Nothing Then
Throw New ArgumentNullException(paramName:=NameOf(table))
End If
If table.Rows.Count = 0 Then
Throw New ArgumentNullException("The source table does not contain any row.", paramName:=NameOf(table))
End If
Dim columnNames As IEnumerable(Of String) = table.Columns.Cast(Of DataColumn)().Select(Function(column) column.ColumnName)
Dim maxColumnValues As Integer() = columnNames.Select(Function(name) table.AsEnumerable().Max(Function(row) If(row.IsNull(name), 0, row(name).ToString().Length))).ToArray()
Dim headerLine As String = "| " & String.Join(" | ", columnNames) & " |"
Dim headerDataDividerLine As String = "| " & String.Join(" | ", maxColumnValues.Select(Function(length) New String("-"c, length))) & " |"
Dim lines As IEnumerable(Of String) = {headerLine, headerDataDividerLine}.Concat(
table.AsEnumerable().Select(
Function(row) "| " & String.Join(" | ", columnNames.Select(Function(name, i) If(row.IsNull(name), "".PadRight(maxColumnValues(i)), row(name).ToString().PadRight(maxColumnValues(i))))) & " |"
)
)
Return String.Join(Environment.NewLine, lines)
End Function
Convertir un objeto IEnumerable a una tabla en formato Markdown:
Código
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Converts the elements of an <see cref="IEnumerable(Of T)"/> into a Markdown table.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' Original C# concept: <see href="https://github.com/jpierson/to-markdown-table/blob/develop/src/ToMarkdownTable/LinqMarkdownTableExtensions.cs"/>
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example that shows how to convert a List(Of String) object to Markdown table.
''' <code language="VB.NET">
''' Dim list As New List(Of String)
''' list.Add("John")
''' list.Add("Doe")
'''
''' Dim markdownTable As String = EnumerableToMarkdownTable(list)
''' Console.WriteLine(markdownTable.ToString())
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <example> This is a code example that shows how to convert a List of a custom type to Markdown table.
''' <code language="VB.NET">
''' Public Class TestClass
''' Public Property ID As Integer
''' Public Property Name As String
''' Public Property Age As Integer
''' End Class
'''
''' Dim list As New List(Of TestClass) From {
''' New TestClass() With {.ID = 1, .Name = "John", .Age = 30},
''' New TestClass() With {.ID = 2, .Name = "Doe" , .Age = 40}
''' }
'''
''' Dim markdownTable As String = EnumerableToMarkdownTable(list)
''' Console.WriteLine(markdownTable.ToString())
''' </code>
''' </example>
''' ----------------------------------------------------------------------------------------------------
''' <typeparam name="T">
''' The type of elements in the collection.
''' </typeparam>
'''
''' <param name="source">
''' The generic collection to convert into a Markdown table.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A string representing the Markdown table.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
Public Shared Function EnumerableToMarkdownTable(Of T)(source As IEnumerable(Of T)) As String
If source Is Nothing OrElse Not source.Any() Then
Throw New ArgumentNullException(paramName:=NameOf(source))
End If
If GetType(T).IsPrimitive OrElse GetType(T) = GetType(String) Then
Return $"| Items |{Environment.NewLine}| ----- |{Environment.NewLine}{String.Join(Environment.NewLine, source.Select(Function(s) $"| {s} |"))}"
End If
Dim properties As PropertyInfo() = GetType(T).GetProperties(BindingFlags.Instance Or BindingFlags.Public Or BindingFlags.GetProperty)
Dim fields As IEnumerable(Of FieldInfo) = GetType(T).GetRuntimeFields().Where(Function(f) f.IsPublic)
Dim gettables As IEnumerable(Of MarkdownColumnData) =
Enumerable.Union(properties.Select(Function(p As PropertyInfo)
Return New MarkdownColumnData With {
.Name = p.Name,
.GetValue = Function(obj) p.GetValue(obj),
.Type = p.PropertyType
}
End Function),
fields.Select(Function(f As FieldInfo)
Return New MarkdownColumnData With {
.Name = f.Name,
.GetValue = Function(obj) f.GetValue(obj),
.Type = f.FieldType
}
End Function))
Dim maxColumnValues As Integer() = source.
Select(Function(x) gettables.Select(Function(p) If(p.GetValue(x)?.ToString()?.Length, 0))).
Union({gettables.Select(Function(p) p.Name.Length)}).
Aggregate(
Enumerable.Repeat(0, gettables.Count()).AsEnumerable(),
Function(accumulate, x) accumulate.Zip(x, Function(a, b) System.Math.Max(a, b))).
ToArray()
Dim columnNames As IEnumerable(Of String) =
gettables.Select(Function(p) p.Name)
Dim headerLine As String =
"| " & String.Join(" | ", columnNames.Select(Function(n, i) n.PadRight(maxColumnValues(i)))) & " |"
Dim isNumeric As Func(Of Type, Boolean) =
Function(type As Type)
Return type = GetType(Byte) OrElse type = GetType(SByte) OrElse type = GetType(UShort) OrElse type = GetType(UInteger) OrElse type = GetType(ULong) OrElse type = GetType(Short) OrElse type = GetType(Integer) OrElse type = GetType(Long) OrElse type = GetType(Decimal) OrElse type = GetType(Double) OrElse type = GetType(Single)
End Function
Dim rightAlign As Func(Of Type, String) =
Function(type As Type)
Return If(isNumeric(type), ":", " "c)
End Function
Dim headerDataDividerLine As String =
"| " &
String.Join("| ", gettables.Select(Function(g, i) New String("-"c, maxColumnValues(i)) & rightAlign(g.Type))) &
"|"
Dim lines As IEnumerable(Of String) =
{
headerLine,
headerDataDividerLine
}.Union(source.
Select(Function(s)
Return "| " & String.Join(" | ", gettables.Select(Function(n, i) If(n.GetValue(s)?.ToString(), "").PadRight(maxColumnValues(i)))) & " |"
End Function))
Return lines.Aggregate(Function(p, c) p & Environment.NewLine & c)
End Function
Eleкtro:
Los dos siguientes métodos sirven para truncar nombres de archivos que superen los 255 caracteres (incluyendo la longitud de la extensión del archivo), acortando la longitud cuanto sea necesario para no sobrepasar dicho límite, y añadiendo puntos suspensivos (…) al final del nombre del archivo.
Eso es lo que hace con los nombres de archivo (file name), no con las rutas (file path).
En caso de enviar como parámetro a cualquiera de estos dos métodos una ruta de archivo (file path), aparte de realizar los ajustes mencionados con el nombre del archivo y, en caso de que la ruta exceda el límite máximo permitido de 260 caracteres (definido en MAX_PATH), se añadirá el prefijo "\\?\" a la ruta para garantizar la compatibilidad de uso con sistemas NTFS que tengan habilitado el soporte para rutas de longitud extendida (es decir, mayores de 260 caracteres).
De esta forma, y además de prevenir el uso de nombres de archivo (file names) inválidos / demasiado largos, además se garantiza que la aplicación que utilice estos métodos para la manipulación o creación de archivos sea "LONG PATH AWARE".
Nota: Los métodos han pasado pruebas usando rutas locales (relativas y absolutas). No han sido probados con rutas UNC ni adaptados para ello.
Leer con detenimiento el bloque de documentación XML para más información.
Código
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' If needed, truncates the length of the specified file name or full file path
''' to comply with Windows OS maximum file name length of 255 characters
''' (including the file extension length).
''' <para></para>
''' If the file name exceeds this limit, it truncates it and
''' adds a ellipsis (…) at the end of the file name.
''' <para></para>
''' If the path exceeds the MAX_PATH limit (260 characters),
''' it adds the "\\?\" prefix to support extended-length paths.
''' <para></para>
''' See also: <see href="https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation"/>
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' This method is particularly useful when dealing with file names or file paths that might exceed
''' the maximum allowed length, preventing potential errors related to file name length limitations
''' when creating files in the drive.
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <param name="filePath">
''' The file name or full file path.
''' </param>
'''
''' <param name="maxFileNameLength">
''' Optional. The maximum character length that the file name can have.
''' Default (and maximum) value is 255.
''' </param>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' The truncated file name or full file path.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Function TruncateLongFilePath(filePath As String, Optional maxFileNameLength As Byte = 255) As String
If String.IsNullOrEmpty(filePath) Then
Throw New ArgumentNullException(paramName:=NameOf(filePath))
End If
If filePath.StartsWith("\\?\", StringComparison.Ordinal) Then
filePath = filePath.Substring(4)
End If
Dim fileInfo As New FileInfo(If(filePath.Length <= 255, filePath, $"\\?\{filePath}"))
TruncateLongFilePath(fileInfo, maxFileNameLength)
Return fileInfo.FullName
End Function
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' If needed, truncates the length of the file name in
''' the source <see cref="FileInfo"/> object to comply with
''' Windows OS maximum file name length of 255 characters
''' (including the file extension length).
''' <para></para>
''' If the file name exceeds this limit, it truncates it and
''' adds a ellipsis (…) at the end of the file name.
''' <para></para>
''' If the path exceeds the MAX_PATH limit (260 characters),
''' it adds the "\\?\" prefix to support extended-length paths.
''' <para></para>
''' See also: <see href="https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation"/>
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <remarks>
''' This method is particularly useful when dealing with file paths that might exceed
''' the maximum allowed length, preventing potential errors related to file name length limitations
''' when creating files in the drive.
''' </remarks>
''' ----------------------------------------------------------------------------------------------------
''' <param name="refFileInfo">
''' The source <see cref="FileInfo"/> object representing a full file path.
''' <para></para>
''' When this method returns, this object contains the file path with the file name truncated.
''' </param>
'''
''' <param name="maxFileNameLength">
''' Optional. The maximum character length that the file name can have.
''' Default (and maximum) value is 255.
''' </param>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Sub TruncateLongFilePath(ByRef refFileInfo As FileInfo, Optional maxFileNameLength As Byte = 255)
If refFileInfo Is Nothing Then
Throw New ArgumentNullException(paramName:=NameOf(refFileInfo))
End If
If maxFileNameLength = 0 Then
Throw New ArgumentException("Value must be greater than zero.", paramName:=NameOf(maxFileNameLength))
End If
If refFileInfo.Name.Length >= maxFileNameLength Then
Dim fileExt As String = refFileInfo.Extension
Dim fileName As String = refFileInfo.Name.Substring(0, maxFileNameLength - 1 - fileExt.Length) & $"…{fileExt}"
Dim directoryName As String = Path.GetDirectoryName(refFileInfo.FullName)
If directoryName.Equals("\\?", StringComparison.Ordinal) Then
refFileInfo = New FileInfo($"\\?\{fileName}")
ElseIf directoryName.StartsWith("\\?\", StringComparison.Ordinal) Then
refFileInfo = New FileInfo(Path.Combine(refFileInfo.DirectoryName, fileName))
Else
Dim fullpath As String = Path.Combine(refFileInfo.DirectoryName, fileName)
refFileInfo = If(fullpath.Length >= 260, ' MAX_PATH
New FileInfo($"\\?\{fullpath}"),
New FileInfo(fullpath))
End If
End If
End Sub
Parado_larga_duracion_ESP:
Dejo un repositorio de utilidades de Excel. Tiene 3 ficheros a día de hoy.
1. Para pasar y leer JSONs
2. Demo de carga de datos por AJAX
3. Utilidades varias, incluida REGEX_MATCH. Va bien para validar formatos en Excel.
https://github.com/allnulled/excel-framework/tree/main
Eleкtro:
La siguiente función, por nombre "GetAssemblyNetTargetType", sirve para determinar si el tipo de un archivo de ensamblado es .NET Framework, .NET Standard o .NET Core.
Modo de empleo:
Código
Dim assembly As Assembly = Assembly.LoadFile("C:\Assembly.dll")
Dim assemblyType As NetTargetType = GetAssemblyNetTargetType(assembly)
Console.WriteLine(assemblyType.ToString())
La función contiene tres validaciones diferentes, separadas por Regiones, aunque por lo general solamente se procesará el bloque de código de la primera validación.
Se ha diseñado así con la intención de funcionar correctamente en diversos escenarios, con errores esperados e inesperados de Reflection, y ya sea teniendo en cuenta si se usa esta función desde una aplicación .NET Framework, o .NET Core.
Código
''' <summary>
''' Specifies the type of a .NET assembly.
''' </summary>
Public Enum NetTargetType
''' <summary>
''' An assembly that targets .NET Framework.
''' </summary>
NetFramework
''' <summary>
''' An assembly that targets .NET Standard.
''' </summary>
NetStandard
''' <summary>
''' An assembly that targets .NET Core.
''' </summary>
NetCore
End Enum
Código
''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Determines whether the specified assembly ia a .NET Framework, .NET Standard or .NET Core assembly.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
''' <returns>
''' A <see cref="NetTargetType"/> value that indicates the type of assembly.
''' </returns>
''' ----------------------------------------------------------------------------------------------------
<DebuggerStepThrough>
Public Shared Function GetAssemblyNetTargetType(assembly As Assembly) As NetTargetType
#Region " Primary validation "
Dim parimaryValidationException As Exception = Nothing
Dim attrib As TargetFrameworkAttribute
Try
attrib = assembly.GetCustomAttributes.OfType(Of TargetFrameworkAttribute).SingleOrDefault()
If attrib?.FrameworkName.StartsWith(".NETFramework", StringComparison.OrdinalIgnoreCase) Then
Return NetTargetType.NetFramework
ElseIf attrib?.FrameworkName.StartsWith(".NETStandard", StringComparison.OrdinalIgnoreCase) Then
Return NetTargetType.NetStandard
ElseIf attrib?.FrameworkName.StartsWith(".NETCore", StringComparison.OrdinalIgnoreCase) Then
Return NetTargetType.NetCore
Else
Throw New NotImplementedException($"Cannot determine type of {NameOf(TargetFrameworkAttribute)}.")
End If
Catch ex As FileNotFoundException When ex.FileName.StartsWith("System.Runtime", StringComparison.OrdinalIgnoreCase)
' This exception will be thrown generally when the current
' running application is targetting .NET Framework
' and Reflection (via method "GetCustomAttributes")
' tries to load "System.Runtime" assembly.
Dim assName As New AssemblyName(ex.FileName)
If assName.Version.Major >= 4 AndAlso assName.Version.Minor <> 0 Then
Return NetTargetType.NetCore
Else
' Ignore and continue with the alternative .NET Core validation.
End If
Catch ex As Exception
parimaryValidationException = ex
' Ignore for now, and continue with the alternative validations.
End Try
#End Region
#Region " .NET Standard alternative validation (when Primary validation failed) "
Dim isNetStandard As Boolean =
assembly.GetReferencedAssemblies().
Any(Function(x) x.Name.Equals("netstandard", StringComparison.OrdinalIgnoreCase))
If isNetStandard Then
Return NetTargetType.NetStandard
End If
#End Region
#Region " .NET Core alternative validation (when Primary validation failed) "
Dim isNetCore As Boolean =
assembly.GetReferencedAssemblies().
Any(Function(x As AssemblyName)
Return (x.Name.Equals("System.Runtime", StringComparison.OrdinalIgnoreCase) _
AndAlso x.Version.Major >= 4 _
AndAlso x.Version.Minor <> 0) _
OrElse ({"System.Collections",
"System.ComponentModel.Primitives",
"System.Drawing.Primitives",
"System.Windows.Forms"
}.Contains(x.Name) _
AndAlso x.Version.Major > 4)
End Function)
If isNetCore Then
Return NetTargetType.NetCore
End If
#End Region
If parimaryValidationException IsNot Nothing Then
Throw parimaryValidationException
End If
Throw New Exception("Cannot determine type of assembly.")
End Function
Eleкtro:
Dos métodos que manipulan el registro de Windows. El primero sirve para crear una nueva entrada en el menú contextual del explorador de Windows al hacer click derecho sobre un tipo de archivo, lo que por lo general sirve para asociar un programa a un tipo/extensión de archivo y poder cargar el archivo haciendo click en esa entrada del menú contextual.
Y el segundo método sirve para borrar la entrada.
Nota: el primer método sirve para crear entradas individuales, no sirve para crear submenús.
Código
''' <summary>
''' Creates a registry key that represents a new entry in the Explorer's context-menu for the specified file type.
''' </summary>
'''
''' <param name="fileType">
''' The file type (typically a file extension) for which to create the entry in the Explorer's context-menu.
''' </param>
'''
''' <param name="keyName">
''' The name of the registry key.
''' </param>
'''
''' <param name="text">
''' The display text for the entry in the Explorer's context-menu.
''' <para></para>
''' This value can be null, in which case <paramref name="keyName"/> will be used as text.
''' </param>
'''
''' <param name="position">
''' The position of the entry in the Explorer's context-menu.
''' <para></para>
''' Valid values are: "top", "middle" and "bottom".
''' <para></para>
''' This value can be null.
''' </param>
'''
''' <param name="icon">
''' The icon to show for the entry in the Explorer's context-menu.
''' <para></para>
''' This value can be null.
''' </param>
'''
''' <param name="command">
''' The command to execute when the entry is clicked in the Explorer's context-menu.
''' </param>
<DebuggerStepThrough>
Public Shared Sub CreateFileTypeRegistryMenuEntry(fileType As String, keyName As String,
text As String, position As String,
icon As String, command As String)
If String.IsNullOrWhiteSpace(fileType) Then
Throw New ArgumentNullException(paramName:=NameOf(fileType))
End If
If String.IsNullOrWhiteSpace(keyName) Then
Throw New ArgumentNullException(paramName:=NameOf(keyName))
End If
If String.IsNullOrWhiteSpace(command) Then
Throw New ArgumentNullException(paramName:=NameOf(command))
End If
If String.IsNullOrEmpty(text) Then
text = keyName
End If
Using rootKey As RegistryKey = Registry.ClassesRoot,
subKey As RegistryKey = rootKey.CreateSubKey($"{fileType}\shell\{keyName}", writable:=True),
subKeyCommand As RegistryKey = subKey.CreateSubKey("command", writable:=True)
subKey.SetValue("", text, RegistryValueKind.String)
subKey.SetValue("icon", icon, RegistryValueKind.String)
subKey.SetValue("position", position, RegistryValueKind.String)
subKeyCommand.SetValue("", command, RegistryValueKind.String)
End Using
End Sub
Código
''' <summary>
''' Deletes an existing registry key representing an entry in the Explorer's context-menu for the specified file type.
''' </summary>
'''
''' <param name="fileType">
''' The file type associated with the registry entry.
''' </param>
'''
''' <param name="keyName">
''' The name of the registry key to delete.
''' </param>
'''
''' <param name="throwOnMissingsubKey">
''' Optional. If <see langword="True"/>, throws an exception if the registry key is not found.
''' <para></para>
''' Default value is <see langword="True"/>.
''' </param>
<DebuggerStepThrough>
Public Shared Sub DeleteFileTypeRegistryMenuEntry(fileType As String, keyName As String, Optional throwOnMissingsubKey As Boolean = True)
If String.IsNullOrWhiteSpace(fileType) Then
Throw New ArgumentNullException(paramName:=NameOf(fileType))
End If
If String.IsNullOrWhiteSpace(keyName) Then
Throw New ArgumentNullException(paramName:=NameOf(keyName))
End If
Using rootKey As RegistryKey = Registry.ClassesRoot
rootKey.DeleteSubKeyTree($"{fileType}\shell\{keyName}", throwOnMissingsubKey)
End Using
End Sub
Navegación
[#] Página Siguiente
[*] Página Anterior