Autor
|
Tema: Leer nombre de carpetas (Leído 6,566 veces)
|
elqueteconte
Desconectado
Mensajes: 36
|
Saludos amigos, Tengo una función que lee el nombre de carpetas tomando en cuenta la selección de un mes, y las mueve a una carpeta principal. Esta función fue desarrollada por Elektro y aquí se las comparto. Public Sub MoveDateDirectories(ByVal year As Integer, ByVal month As Integer, ByVal dateFormat As String, ByVal sourceDir As String, ByVal targetDir As String) If (CStr(year).Length <> 4I) Then Throw New ArgumentOutOfRangeException(paramName:="year", message:="A value of 4 digits' is required.") 'ElseIf (month < 1I) OrElse (month > 12I) Then ' Throw New ArgumentOutOfRangeException(paramName:="month", message:="A value from range '1' to '12' is required.") 'ElseIf (dateFormat.Replace("y", "").Replace("M", "").Replace("d", "").Length <> 0) Then ' Throw New NotImplementedException(message:="Specified date format is not implemented, only 'yyyy', 'MM' and 'dd' are interchangeable.") 'ElseIf Not Directory.Exists(sourceDir) Then ' Throw New DirectoryNotFoundException(message:=String.Format("Source directory not found: '{0}'", targetDir)) 'ElseIf Not Directory.Exists(targetDir) Then ' Throw New DirectoryNotFoundException(message:=String.Format("Target directory not found: '{0}'", targetDir)) Else Dim sourceDirInfo As New DirectoryInfo(sourceDir) Dim targetDirInfo As New DirectoryInfo(targetDir) ' Obtengo una colección con los nombres de directorio con el formato de fecha especificado. (ej. de Octubre 2015: 20151001 ... 20151031) Dim dateDirNames As IEnumerable(Of String) = From day As Integer In Enumerable.Range(1, DateTime.DaysInMonth(year, month)) Select dateFormat.Replace("yyyy", CStr(year)). Replace("MM", CStr(month).PadLeft(2, "0"c)). Replace("dd", CStr(day).PadLeft(2, "0"c)) ' Obtengo una colección con las rutas absolutas de los directorios que cumplen los requisitos. Dim directories As IEnumerable(Of DirectoryInfo) = From dirInfo As DirectoryInfo In sourceDirInfo.EnumerateDirectories("*", SearchOption.TopDirectoryOnly) Where dateDirNames.Contains(dirInfo.Name) ' Un simple mensaje de información o aviso cuando no se encuentra ningún directorio el cual mover. If (Not directories.Any) Then Dim msg As String = String.Format("No ha sido encontrado ningún directorio en '{0}' que cumpla las condiciones de formato de fecha.", sourceDirInfo.FullName) MessageBox.Show(msg, " ", MessageBoxButtons.OK, MessageBoxIcon.Information) Else ' Por último, muevo los directorios que cumplieron las condiciones de formato de fecha. For Each dirInfo As DirectoryInfo In directories Debug. WriteLine(String. Format("Moviendo: {0}", dirInfo. FullName)) Try dirInfo.MoveTo(Path.Combine(targetDirInfo.FullName, dirInfo.Name)) Catch ex As Exception Throw #Else MessageBox.Show(ex.Message & Environment.NewLine & ex.StackTrace, "By Elektro", MessageBoxButtons.OK, MessageBoxIcon.Error) #End If End Try Next dirInfo ' MessageBox.Show("Operación finalizada.", "By Elektro", MessageBoxButtons.OK, MessageBoxIcon.Information) End If ' Not directories.Any End If ' dateFormat... End Sub
Esta trabaja perfecto sin problemas; salvo que ahora necesito adecuarla de manera que sea posible mover días, es decir, si el usuario selecciona desde el 01-12-2015 hasta el 15-12-2015 (ambos inclusive); el proceso solo mueva esos días. Alguien podría orientarme de como adecuar esta función para que haga lo que necesito? Desde ya mil gracias...
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
Esta función fue desarrollada por Elektro y aquí se las comparto. Que conste que agradezco cualquier mención hacia mi persona como autor de algo, sin embargo, no quiero que se me asocie con malos hábitos de programación, en el código hay una gran ausencia de indentación, ya que lo has modificado bastante, los comentarios abusivos (y en español, cosa que lo hice para el caso) y el desorden en general que hay montado en ese bloque de código xD.
Ese método está quedando excesivamente grande. Cuanto más grande o complejo sea un método más complejo será también para el compiler/intérprete (complejidad ciclomática). Vamos a separar el trabajo en varios métodos, primero una función para obtener los directorios, segundo un overload de esa función para poder especificar un rango de días, y por último un método para mover los directorios obtenidos. y... voilà: <DebuggerStepThrough> Public Iterator Function SelectDirectories(ByVal sourceDir As String, ByVal year As Integer, ByVal month As Integer, ByVal days As IEnumerable(Of Integer), ByVal dateFormat As String) As IEnumerable(Of DirectoryInfo) If (CStr(year).Length <> 4) Then Throw New ArgumentOutOfRangeException(paramName:="year", actualvalue:=year, message:="A value of 4 digits is required.") ElseIf (month < 1) OrElse (month > 12) Then Throw New ArgumentOutOfRangeException(paramName:="month", actualvalue:=month, message:="A value from range '1' to '12' is required.") ElseIf (dateFormat.Replace("y", ""). Replace("M", ""). Replace("d", "").Length <> 0) Then Throw New NotImplementedException( message:="Specified date format is not implemented, only 'yyyy', 'MM' and 'dd' are interchangeable.") ElseIf Not Directory.Exists(sourceDir) Then Throw New DirectoryNotFoundException( message:=String.Format("Source directory not found: '{0}'", sourceDir)) End If Dim sourceDirInfo As New DirectoryInfo(sourceDir) ' Obtengo una colección con los nombres de directorio con el formato de fecha especificado. ' (ej. de Octubre 2015: 20151001 ... 20151031) Dim dateDirNames As IEnumerable(Of String) = From day As Integer In days Select dateFormat.Replace("yyyy", CStr(year)). Replace("MM", CStr(month).PadLeft(2, "0"c)). Replace("dd", CStr(day).PadLeft(2, "0"c)) ' Itero y devuelvo una colección con las rutas absolutas de los directorios que cumplen los requisitos. For Each dirInfo As DirectoryInfo In sourceDirInfo.EnumerateDirectories("*", SearchOption.TopDirectoryOnly) If dateDirNames.Contains(dirInfo.Name) Then Yield dirInfo End If Next End Function <DebuggerStepThrough> Public Function SelectDirectories(ByVal sourceDir As String, ByVal year As Integer, ByVal month As Integer, ByVal dateFormat As String) As IEnumerable(Of DirectoryInfo) Dim days As IEnumerable(Of Integer) = Enumerable.Range(1, DateTime.DaysInMonth(year, month)) Return SelectDirectories(sourceDir, year, month, days, dateFormat) End Function <DebuggerStepThrough> Public Sub MoveDirectories(ByVal directories As IEnumerable(Of DirectoryInfo), ByVal targetDir As String) If Not Directory.Exists(targetDir) Then Throw New DirectoryNotFoundException( message:=String.Format("Target directory not found: '{0}'", targetDir)) Else Dim trgDirInfo As New DirectoryInfo(targetDir) For Each srcDirInfo As DirectoryInfo In directories If Not Directory.Exists(srcDirInfo.FullName) Then Throw New DirectoryNotFoundException( message:=String.Format("Source directory not found: '{0}'", srcDirInfo.FullName)) Else Debug. WriteLine(String. Format("Moviendo: {0}", srcDirInfo. FullName)) srcDirInfo.MoveTo(Path.Combine(trgDirInfo.FullName, srcDirInfo.Name)) End If Next End If End Sub
PD: Lo he escrito al vuelo, no lo he testeado, ya no conservo la estructura de carpetas para testearlo, pero creo que no hay ninguna fisura en el código.
Ejemplo de uso: Seleccionar las carpetas del mes entero: Dim directories As IEnumerable(Of DirectoryInfo) = SelectDirectories("C:\Directorio\", 2015, 11, "formato de fecha")
o de un rango de días (del día 1 al 15): Dim directories As IEnumerable(Of DirectoryInfo) = SelectDirectories("C:\Directorio\", 2015, 11, Enumerable.Range(1, 15), "formato de fecha")
o de ciertos dias: Dim directories As IEnumerable(Of DirectoryInfo) = SelectDirectories("C:\Directorio\", 2015, 11, {5, 3, 9, 12}, "formato de fecha")
y por último, mover los directorios: MoveDirectories(directories, "C:\Destino\")
Saludos
|
|
« Última modificación: 9 Noviembre 2015, 17:24 pm por Eleкtro »
|
En línea
|
|
|
|
elqueteconte
Desconectado
Mensajes: 36
|
Hola Elektro buen día;
Gracias mil por el apoyo, tendré muy presente tus recomendaciones.
Te envié por MP el avance que he adelantado con respecto a esto, con el fin de que (dentro de tus posibilidades) le direas un vistazo y me orientaras al respecto.
Estoy totalmente de acuerdo contigo, no se puede hacer un solo método que haga multiples funciones lo ideal es uno por mes y otro por semana.
Quiero tambien disculparme si he cometido alguna falta al mencionar que la función la habias hecho tu, pero me pareció poco etico y profesional que yo me atribuyera algo que no me pertenece, sería un plagio.
Desde ya mil gracias por tu constante y valioso apoyo....
Seguiremos en contacto.
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
Quiero tambien disculparme si he cometido alguna falta al mencionar que la función la habias hecho tu, pero me pareció poco etico y profesional que yo me atribuyera algo que no me pertenece, sería un plagio. No xD, para nada, todo lo contrario, solo que el código estaba un poco ""feo"" y yo soy muy "tiquismiquis" para ciertas cosas. Sobre lo demás, te comentaré en privado. Saludos!
|
|
|
En línea
|
|
|
|
elqueteconte
Desconectado
Mensajes: 36
|
No xD, para nada, todo lo contrario, solo que el código estaba un poco ""feo"" y yo soy muy "tiquismiquis" para ciertas cosas.
Sobre lo demás, te comentaré en privado.
Saludos!
Limpiando el código como me comentas, tenemos entonces: Public Sub MoveDateDirectories(ByVal year As Integer, ByVal month As Integer, ByVal dateFormat As String, ByVal sourceDir As String, ByVal targetDir As String) If (CStr(year).Length <> 4I) Then Throw New ArgumentOutOfRangeException(paramName:="year", message:="A value of 4 digits' is required.") Else Dim sourceDirInfo As New DirectoryInfo(sourceDir) Dim targetDirInfo As New DirectoryInfo(targetDir) Dim dateDirNames As IEnumerable(Of String) = From day As Integer In Enumerable.Range(1, DateTime.DaysInMonth(year, month)) Select dateFormat.Replace("yyyy", CStr(year)). Replace("MM", CStr(month).PadLeft(2, "0"c)). Replace("dd", CStr(day).PadLeft(2, "0"c)) Dim directories As IEnumerable(Of DirectoryInfo) = From dirInfo As DirectoryInfo In sourceDirInfo.EnumerateDirectories("*", SearchOption.TopDirectoryOnly) Where dateDirNames.Contains(dirInfo.Name) If (Not directories.Any) Then Dim msg As String = String.Format("No ha sido encontrado ningún directorio en '{0}' que cumpla las condiciones de formato de fecha.", sourceDirInfo.FullName) MessageBox.Show(msg, " ", MessageBoxButtons.OK, MessageBoxIcon.Information) Else For Each dirInfo As DirectoryInfo In directories Debug. WriteLine(String. Format("Moviendo: {0}", dirInfo. FullName)) Try dirInfo.MoveTo(Path.Combine(targetDirInfo.FullName, dirInfo.Name)) Catch ex As Exception Throw MessageBox.Show(ex.Message & Environment.NewLine & ex.StackTrace, "By Elektro", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try Next dirInfo MessageBox.Show("Operación finalizada.", "By Elektro", MessageBoxButtons.OK, MessageBoxIcon.Information) End If End If End Sub
Esta es la que en la actualizadad hace el movimiento de los directorios; ahora bien en mi evento Click del botón aceptar tengo: Private Sub BtAccept_Click(ByVal sender As Object, ByVal e As EventArgs) _ Handles BtAccept.Click Dim monthNumber As Integer = Me.DTPMonth.Value.Month Dim dateDir As String = DateUtil.GetDateDirPath("es-ES", Me.fdg.SelectedPath, Me.year, monthNumber) ' Creo el directorio con fecha (si no existe). DateUtil.CreateDirectory(dateDir) If RBMonth.Checked Then DateUtil.MoveDateDirectories(Me.year, monthNumber, DateUtil.DirNameFormat, Me.fdg.SelectedPath, dateDir) Else [b] 'El usuario a seleccionado empaquetar solo una semana en particular aqui iria el codigo que corresponde al movimiento de las carpetas que esten dentro del rango de las indicadas por el usuario.[/b] End If ' Merge text files. DateUtil.FindAndMergeFiles(Me.fdg.SelectedPath, Me.CMBComp) End Sub
De acuerdo a lo que me estas indicando yo debería: 1.- Quitar la función MoveDateDirectories 2.- Copiar y pegar las funciones que haz desarrollado 3.- En el If si el usuario ha solicitado hacerlo mensual colocar: Dim directories As IEnumerable(Of DirectoryInfo) = SelectDirectories(dateDir, Me.year, monthNumber) MoveDirectories(directories, Path.Combine(targetDirInfo.FullName, dirInfo.Name))
En caso de haber seleccionado una semana sería: Dim directories As IEnumerable(Of DirectoryInfo) = SelectDirectories(dateDir, Me.year, monthNumber,Enumerable.Range(1, 15)) MoveDirectories(directories, Path.Combine(targetDirInfo.FullName, dirInfo.Name))
Es así como lo entiendo. Desde ya gracias....!
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
Lo has entendido todo a la perfección y lo has sabido adaptar al código sin aydua . Solo que, aquí, no se si lo has entendido del todo, yo creo que deberías averiguar el día/semana que haya seleccionado en tu control DateTimePicker, y usarlo en el rango, por que esta función lo que hace es devolver un rango de valores desde X hasta Y: Enumerable.Range(desde_primer_dia_X, hasta_último_dia_Y): Dim directories As IEnumerable(Of DirectoryInfo) = SelectDirectories(dateDir, Me.year, monthNumber, Enumerable.Range(1, semana))
Si solo quieres seleccionar la primera semana, deberías utilizarlo así Enumerable.Range(1, 7)Auqnue bueno, eso es como tú lo quieras hacer. Saludos!
|
|
« Última modificación: 9 Noviembre 2015, 21:34 pm por Eleкtro »
|
En línea
|
|
|
|
elqueteconte
Desconectado
Mensajes: 36
|
Lo has entendido todo a la perfección y lo has sabido adaptar al código sin aydua . Solo que, aquí, no se si lo has entendido del todo, yo creo que deberías averiguar el día/semana que haya seleccionado en tu control DateTimePicker, y usarlo en el rango, por que esta función lo que hace es devolver un rango de valores desde X hasta Y: Enumerable.Range(desde_primer_dia_X, hasta_último_dia_Y): Dim directories As IEnumerable(Of DirectoryInfo) = SelectDirectories(dateDir, Me.year, monthNumber, Enumerable.Range(1, semana))
Aunque bueno, eso es como tú lo quieras hacer. Saludos! Gracias, gracias, gracias jejejejeje No entendí lo ultimo, acerca de la función de los días; la idea es que el usuario coloque al menos 2 días, es decir, desde el 01 al 02, pero no va a poder seleccionar varios días salteado por ejemplo, 01, 03, 05 y 09. En este caso sería como seleccionar entre el 01 y el 09. So, siempre habrá un rango que será igual o mayor a dos días y menor al ultimo día del mes. La fecha desde no puede ser posterior a la fecha hasta y la fecha hasta no puede ser inferior a la fecha desde, estas son reglas que se colocarán en la validación del campo con el evento onChange. En este caso te pregunto como sería la función Enumerable.Range ? Otra cosa: Al función SelectDirectories espera 4 parámetros y en el llamaddo yo le estoy colocando solo 3, me falta el dateFormat, de donde lo saco? Dim directories As IEnumerable(Of DirectoryInfo) = DateUtil.SelectDirectories(dateDir, Me.year, monthNumber, ME FALTA ESTE PARÁMETRO)
De nuevo gracias mil.
|
|
« Última modificación: 9 Noviembre 2015, 22:09 pm por elqueteconte »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
desde el 01 al 02
entre el 01 y el 09.
siempre habrá un rango
En este caso te pregunto como sería la función Enumerable.Range ? Enumerable.Range(inicio, fin)
Enumerable.Range(1, 2)
Enumerable.Range(1, 9)
Otra cosa: Al función SelectDirectories espera 4 parámetros y en el llamaddo yo le estoy colocando solo 3, me falta el dateFormat, de donde lo saco? Dim directories As IEnumerable(Of DirectoryInfo) = DateUtil.SelectDirectories(dateDir, Me.year, monthNumber, ME FALTA ESTE PARÁMETRO)
El método original que estaba sutilizando era este: Public Sub MoveDateDirectories(ByVal year As Integer, ByVal month As Integer, ByVal dateFormat As String, ByVal sourceDir As String, ByVal targetDir As String)
Revisa en el código fuente que valor le estabas enviando al parámetro dateFormat de ese método. Usa el mismo valor al llamar a esta nueva función. No recuerdo el formato, está escrito en tu código fuente y también en alguna de las páginas de tus preguntas anteriores, era un string más o menos así "MM-dd-YYYY". Saludos
|
|
« Última modificación: 9 Noviembre 2015, 22:15 pm por Eleкtro »
|
En línea
|
|
|
|
elqueteconte
Desconectado
Mensajes: 36
|
Saludos; 1.- Enumerable.Range(inicio, fin)
Donde inicio y fin son el valor del DateTmePiker que seleccionó el usuario. Sería algo como: Dim directories As IEnumerable(Of DirectoryInfo) = SelectDirectories(dateDir, Me.year, monthNumber, Enumerable.Range(Me.DTPSince.Value, Me.DTPUntil.Value))
Pero dado que el valor que espera el método Enumerable es un entero y el valor que tiene el objeto DTPSince es un string hay que hacer la conversión, que inicialmente sería con esto: Convert.ToInt32(DTPUntil.Value.ToString("yyyyMMdd"))
Es esto correcto? Así quedaría la definición de la variable: Dim directories As IEnumerable(Of DirectoryInfo) = SelectDirectories(dateDir, Me.year, monthNumber, Enumerable.Range(Convert.ToInt32(DTPSince.Value.ToString("yyyyMMdd")), Convert.ToInt32(DTPUntil.Value.ToString("yyyyMMdd"))))
2.- La definición de la variable sería entonces asi: Dim directories As IEnumerable(Of DirectoryInfo) = DateUtil.SelectDirectories(dateDir, Me.year, monthNumber, DateUtil.DirNameFormat)
Como quedaría el llamado al metodo? Pues he intentado con la variable targetDirInfo y dirInfo pero me está dando error de no declarado o inaccesible. Gracias!
|
|
« Última modificación: 10 Noviembre 2015, 16:12 pm por elqueteconte »
|
En línea
|
|
|
|
elqueteconte
Desconectado
Mensajes: 36
|
Saludos, Me puse a estudiar el metodo Enumerable.Range y me día cuenta que lo que decía antes era un soberano disparate pues el range utiliza el valor del día de la fecha inicial (para mi caso especíifico) y el segundo valor es la cantida de días; es decir; que si la fecha de inicio es 01-11-2015 y la fecha fin es 12-11-2015; entonces el primero valor será el 1 y el segundo valor será el 11. Esto significa que debo sacar una operación matematica pra calcular la diferencia. Dim InitialDate As Date = DTPSince.Value Dim FinalDate As Date = DTPUntil.Value Dim tspan As TimeSpan Dim differenceInDays As Integer tspan = InitialDate - FinalDate differenceInDays = tspan.Days
Una vez obtenido esto la definición de la variable directories sería: Dim directories As IEnumerable(Of DirectoryInfo) = SelectDirectories(dateDir, Me.year, monthNumber, Enumerable.Range(InitialDate.Day, differenceInDays))
Pero me sigue dando error de IEnumerable (Of Integer) to String. Que estoy haciendo mal?
|
|
|
En línea
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
AYUDA CON BAT, LEER NOMBRE DE ARCHIVO...
Scripting
|
elecktra
|
3
|
3,102
|
28 Noviembre 2008, 00:56 am
por Darioxhcx
|
|
|
Eliminar carpetas segun su nombre BATCH
Scripting
|
Fabiang
|
1
|
5,335
|
16 Julio 2010, 20:34 pm
por Fabiang
|
|
|
Leer archivo con nombre variable
Scripting
|
Jonha000
|
3
|
3,627
|
10 Agosto 2010, 15:42 pm
por EddyW
|
|
|
Script copiar carpetas y cambiar de nombre
Scripting
|
espantaburros
|
0
|
2,266
|
22 Junio 2014, 21:13 pm
por espantaburros
|
|
|
Leer carpetas y sub carpetas C# unity
Programación C/C++
|
aspiazu
|
0
|
1,838
|
5 Abril 2017, 22:01 pm
por aspiazu
|
|