Páginas

miércoles, 24 de diciembre de 2014

Python: Funcion para convertir fecha de Excel a formato d-m-y


(exceldate.py)

import datetime

def exceldate(serial):
    seconds = (serial - 25569) * 86400.0
    d = datetime.datetime.utcfromtimestamp(seconds)
    return d.strftime('%d-%m-%y')
if __name__ == "__main__":
    exceldate()
   

Y asi se utiliza:

>>> from exceldate import exceldate
>>> d = exceldate(42031.0)
>>> d
'27-01-15'

miércoles, 17 de diciembre de 2014

Python: Objetos, propiedades y metodos en la libreria xlrd

Abrir un libro:

reporte = xlrd.open_workbook(path)

Metodos y propiedades del objeto libro:

actualfmtcount
addin_func_names
biff2_8_load
biff_version
builtinfmtcount
codepage
colour_map
countries
datemode
derive_encoding
dump
encoding
fake_globals_get_sheet
filestr
font_list
format_list
format_map
formatting_info
get2bytes
get_record_parts
get_record_parts_conditional
get_sheet
get_sheets
getbof
handle_boundsheet
handle_builtinfmtcount
handle_codepage
handle_country
handle_datemode
handle_externname
handle_externsheet
handle_filepass
handle_name
handle_obj
handle_sheethdr
handle_sheetsoffset
handle_sst
handle_supbook
handle_writeaccess
initialise_format_info
load_time_stage_1
load_time_stage_2
logfile
mem
name_and_scope_map
name_map
name_obj_list
names_epilogue
nsheets
on_demand
palette_record
parse_globals
props
ragged_rows
raw_user_name
read
release_resources
sheet_by_index
sheet_by_name
sheet_loaded
sheet_names
sheets
style_name_map
unload_sheet
use_mmap
user_name
verbosity
xf_list
xfcount


Metodos y propiedades de la hoja:

automatic_grid_line_colour
bf
biff_version
book
bt
cached_normal_view_mag_factor
cached_page_break_preview_mag_factor
cell
cell_note_map
cell_type
cell_value
cell_xf_index
col
col_label_ranges
col_slice
col_types
col_values
colinfo_map
columns_from_right_to_left
computed_column_width
cooked_normal_view_mag_factor
cooked_page_break_preview_mag_factor
default_additional_space_above
default_additional_space_below
default_row_height
default_row_height_mismatch
default_row_hidden
defcolwidth
dump
fake_XF_from_BIFF20_cell_attr
first_visible_colx
first_visible_rowx
fixed_BIFF2_xfindex
formatting_info
gcw
gridline_colour_index
gridline_colour_rgb
handle_feat11
handle_hlink
handle_msodrawingetc
handle_note
handle_obj
handle_quicktip
handle_txo
has_pane_record
horizontal_page_breaks
horz_split_first_visible
horz_split_pos
hyperlink_list
hyperlink_map
insert_new_BIFF20_xf
logfile
merged_cells
name
ncols
nrows
number
panes_are_frozen
put_cell
put_cell_ragged
put_cell_unragged
ragged_rows
read
remove_splits_if_pane_freeze_is_remov
req_fmt_info
rich_text_runlist_map
row
row_label_ranges
row_len
row_slice
row_types
row_values
rowinfo_map
scl_mag_factor
sheet_selected
sheet_visible
show_formulas
show_grid_lines
show_in_page_break_preview
show_outline_symbols
show_sheet_headers
show_zero_values
split_active_pane
standardwidth
string_record_contents
tidy_dimensions
update_cooked_mag_factors
utter_max_cols
utter_max_rows
verbosity
vert_split_first_visible
vert_split_pos
vertical_page_breaks
visibility


Metodos y propiedades de las celdas:

capitalize
center
count
decode
encode
endswith
expandtabs
find
format
index
isalnum
isalpha
isdigit
islower
isspace
istitle
isupper
join
ljust
lower
lstrip
partition
replace
rfind
rindex
rjust
rpartition
rsplit
rstrip
split
splitlines
startswith
strip
swapcase
title
translate
upper
zfill

martes, 9 de diciembre de 2014

Python: Operaciones con sets.

En resumen, ahí esta el gráfico:


Python: Crear un archivo HTML basado en una hoja de Excel


La idea es que Python lea las celdas del archivo excel y vaya escribiendo el archivo HTML un dato a la vez:

import xlrd
def upload():
    mobile = open('d:/rubenBk/HTML/mobile quota.html', 'w')
    report = xlrd.open_workbook('D:/RubenBK/Reports/cctableruben.xlsm')
    sheet = report.sheet_by_name('Licencias')
    mobile.write('<body style="background-color:yellow">')
    mobile.write('<table>')
    for r in range(sheet.nrows):
        mobile.write('<tr>') #creates the row
        for c in range(sheet.ncols):
            if unicode(sheet.cell_value(r,c)).encode('utf-8') != '': #if the cell contais data, apply a border to it.
                mobile.write('<td style = "border-style:solid; border-width:1px">' + unicode(sheet.cell_value(r,c)).encode('utf-8') + '</td>')#fills data in row               
            else:
                mobile.write('<td>' + unicode(sheet.cell_value(r,c)).encode('utf-8') + '</td>')#fills data in row
           
    mobile.write('</table>')   
    mobile.write('<a href = "D:/RubenBK/HTML/Home.html">Home</a>')
    mobile.write('</body>')
if __name__ == '__main__':
    upload()

viernes, 5 de diciembre de 2014

Python: Abrir ventana para seleccionar archivos

Una maravilla esto, super util para hacer las aplicaciones mas 'user friendly':

    import Tkinter, tkFileDialog, re
    root = Tkinter.Tk() #esto se hace solo para eliminar la ventanita de Tkinter 
    root.withdraw() #ahora se cierra 
    file_path = tkFileDialog.askopenfilename() #abre el explorador de archivos y guarda la seleccion en la variable!
    
    #Ahora para guardar el directorio donde se encontraba el archivo seleccionado:
    match = re.search(r'/.*\..+', file_path)#matches name of file
    file_position = file_path.find(match.group()) #defines position of filename in file path

    save_path = file_path[0: file_position+1] #extracts the saving path.

  

martes, 18 de noviembre de 2014

Python: Como escoger aleatoriamente un elemento de una lista.


Para este ejemplo creo primero una lista de videos, y hago que a una cierta hora se reproduzcan de manera aleatoria:

import os, random
from time import ctime


#la lista de videos:

loneRanger = "C:/Users/Ruben Torres/Videos/The Lone Ranger Opening Theme Song.mp4"
flintStones = "C:/Users/Ruben Torres/Videos/The Flintstones Theme Song.mp4"
saved = "C:/Users/Ruben Torres/Videos/Saved By The Bell (Theme Song).mp4"
mazinger = "C:/Users/Ruben Torres/Videos/mazinger.mp4"
ninjaTurtles = "C:/Users/Ruben Torres/Videos/Ninja Turtles.mp4"


songs = [loneRanger, flintStones, saved, mazinger, ninjaTurtles]

#creo un while loop que se culmina a las 6 de la tarde

while ctime()[11:19] != '18:00:00':
    pass


#reproduce aleatoriamente uno de los videos

os.startfile(random.choice(songs))

jueves, 9 de octubre de 2014

Python: Crear directorios con os.mkdir()

Una cosa importante: Si se quiere crear un directorio con mkdir, se debe crear nivel por nivel
Si solo tengo el D:/ primero tengo que crear D:/Ruben y luego crear D:/Ruben/PL0001

from os import mkdir
from os.path import exists

destination = D:/Ruben/
pl = PL0001

if exists(destination): #si ya existiere el directorio
    if exists(destination+pl): #verifica si existe el subdirectorio
         destSubfolder = destination+pl
     else:
          mkdir(destination+pl)
#si no existe crea el subdirectorio
          destSubfolder = destination+pl
else: #si no existe el directorio
    mkdir(destination) #crea el directorio
    mkdir(destination+pl) #crea el subdirectorio
    destSubfolder = destination+pl

miércoles, 8 de octubre de 2014

Python: Extraer archivos adjuntos desde Outlook

Digamos que tengo 1000 numeros de PL y mi base de datos es mi correo electronico, con este script puedo crear una carpeta con todos los documentos que correspondan a dicha importacion:

from win32com import client
from os import mkdir
from os.path import exists

pl = "0002181407160MHMA07K" #el numero de referencia a buscar en el mail
destination = 'D:/' #la carpeta raiz de destino
try:
    ol= client.Dispatch("Outlook.Application")
#objeto de outlook
    ns = ol.GetNameSpace("MAPI") #objeto NameSpace
except:
    print "There was a problem accessing Outlook"
    raw_input()

#crea un directorio con el nombre del contrato, si es que no existe ya.
if exists(destination+pl):
    destSubfolder = destination+pl
else:
    mkdir(destination+pl)
    destSubfolder = destination+pl

try:
    counter = 0 #contará el numero de attachments encontrados
    print 'Extracting attachments from %s...' %pl
    for fold in ns.folders:
#busca en cada carpeta
        for f in fold.folders: #busca en la coleccion de subcarpetas
            if f.Name == "Inbox": #solo en las subcarpetas Inbox
                for it in f.items: #por cada mail en la colecion de mail items
                    if pl in it.Subject: #si encuentra el pl en el asunto
                        attNumber = it.Attachments.Count #the number of attachments
                        if attNumber > 0: #only if there are attachments in the msg
                            for n in range(attNumber):
                                att = it.Attachments.Item(n+1)
# the file
                                attName = att.DisplayName #the file name
                                if not 'image' in attName: #excludes image.001 files
                                    print attName
                                    att.SaveAsfile(destSubfolder+ '/'+ attName)
                                    counter +=1

                                    #crea una carpeta con el nombre del pl en el root
                       
    print "Total attacments extracted: %i" %counter
    raw_input()
except:
    print "There was a problem extracting files"
    raw_input()


VBA Outlook: Como navegar por los objetos de Outlook usando VBA


El orden es el siguiente:

El NameSpace
Las carpetas
Las subcarpetas (si hay)
Los items
Bueno y todo lo que tengan los items, llegar hasta aquí era lo mas importante. Luego explorando los metodos y atributos que tiene cada objeto se pueden hacer maravillas.

Sub findPl()
'El Namespace es el objeto principal
Set ns = Outlook.GetNamespace("MAPI")
'Luego vienen los folders, los subfolders, y por ultimo los items:
For Each fold In ns.Folders
    For Each f In fold.Folders
        For Each it In f.Items
            MsgBox it.Subject
        Next it
    Next f
   
Next fold

End Sub

martes, 30 de septiembre de 2014

Python: Mi script favorito

Este es mi script favorito hasta ahora porque me ahorra un montón de tiempo al ingresar datos de importaciones a mi reporte. Automaticamente suma facturas, cuenta cajas, pesos, obtiene datos de guias aereas y bls y lo carga todo a mi reporte:

print 'Scanning invoices...'
import re, xlrd, os, os.path, openpyxl, pdfminer
#invoice variables
fob = 0
freight = 0
insurance = 0
total = 0
invoice = []
plNum = ''
invoiceFound = 'false'
#pl variables
writeFile = open("d:/pls.txt", "w")
cases =[]
gweight =[]
nweight=[]
volume = []
plFound = 'false'
#bl variables
blNumber = ''
containers = []
blCases =[]
blWeight =[]
blVolume =[]
blFound = 'false'
#first set the path
path= "d:/Loader/"
#look for invoices-------------------------------------------------------------------------------------------------------------------------------
#try:
for file in os.listdir(path):
    match = re.search(r'.*\.[xlXL]\w+', file)
    if match:
        wb = xlrd.open_workbook(path+file)
        sht = wb.sheet_by_index(0)
        n = sht.nrows
        #identifies invoice based on keyword placement
        if "Huawei" in sht.cell_value(0,2) or "Huawei" in sht.cell_value(4, 2):
            invoiceFound = 'true'
            #Identifies the invoce template
            if "Huawei" in sht.cell_value(0,2): #The old template
                fob = fob + float(sht.cell_value((sht.nrows -4),13))
                freight = freight + float(sht.cell_value((sht.nrows -3),13))
                insurance = insurance + float(sht.cell_value((sht.nrows -2),13))
                total = total + float(sht.cell_value(sht.nrows-1,13))
                invoice.append(sht.cell_value(3,2)[11:])
                plNum = sht.cell_value(7,2)[8:]
            elif 'Huawei Device Co., Ltd.' in sht.cell_value(4,2): #Device template
                cellContent = sht.cell_value(sht.nrows - 7, 8)
                cellContent = cellContent.split()
                for n in range(len(cellContent)):
                    if ',' in cellContent[n]:
                        cellContent[n] = cellContent[n].replace(',', '.')
                fob = fob+float(cellContent[0])
                freight = freight + float(cellContent[1])
                insurance = insurance + float(cellContent[2])
                total = total + float(cellContent[3])
                invoice.append(sht.cell_value(8,7))
                plNum = sht.cell_value(10,7)
            else: #the new template
                for row in range(n):
                    if "FOB" in sht.cell_value(row, 6):
                        fob = fob + float(sht.cell_value(row,7))
                        freight = freight + float(sht.cell_value(row+1, 7))
                        insurance = insurance + float(sht.cell_value(row+2, 7))
                        #sometimes there is a USD in the Total cell so we need to suppress it
                        if 'USD'in str(sht.cell_value(row+3,7)):
                            total = total + float(sht.cell_value(row+3,7)[3:])
                        else:
                            total = total + float(sht.cell_value(row+3,7))
                        invoice.append(sht.cell_value(8,7))
                        plNum = sht.cell_value(sht.nrows-2,2)       
   
if invoiceFound == 'true':
    print "FOB: %f, Flete: %f, seguro: %f, Total: %f" %(fob, freight, insurance, total)
else:
    print 'No invoices found.'
print
#except:
    #print 'There was a problem scanning invoices. No information could be retreived.'
    #print
   
#look for PLs------------------------------------------------------------------------------------------------------------------------------------
print 'Scanning PLs...'
try:
    for file in os.listdir(path):
        match = re.search(r'.*\.[xlXL]\w+', file)
        if match:
            wb = xlrd.open_workbook(path+file)
            sht = wb.sheet_by_index(0)
            n = sht.nrows
            for row in range(n):
                if "Total:" in unicode(sht.cell_value(row,0)):
                    plFound = 'true'
                    writeFile.write(sht.cell_value(row, 0)+"\n")
    writeFile.close()
    if plFound == 'true':
        summary = open("d:/pls.txt")
        for line in summary:
            matchTotalCases = re.search(r'Total:\d*CASES\s', line)
            matchGrossWeight = re.search(r'gross\sweight\(KG\):\d*\.?\d*\s', line)
            matchNetWeight = re.search(r'net\sweight\(KG\):\d*\.?\d*\s', line)
            matchVolume = re.search(r'volume\(CBM\):\d*\.?\d*\s', line)
            if matchTotalCases:
                stringCases = matchTotalCases.group()
                cases.append(int(stringCases[6:-6]))
            if matchGrossWeight:
                stringGrossWeigth = matchGrossWeight.group()
                gweight.append(float(stringGrossWeigth[17:-1])) 
            if matchNetWeight:
                stringNetWeight = matchNetWeight.group()
                nweight.append(float(stringNetWeight[15:-1]))
            if matchVolume:
                stringVolume = matchVolume.group()
                volume.append(float(stringVolume[12:-1]))
        tcases = sum(cases)
        tgweight = sum(gweight)
        tnweight = sum(nweight)
        tvolume = sum(volume)
        print "Total cases: %i, gross weight: %f,  net weight: %f, volume: %f" %(sum(cases), tgweight, tnweight, tvolume)
       
    else:
        print 'No Packing Lists Found.'
except:
    print 'There was a problem scanning PLs. No information could be retreived.'
    print
       
#look for BLS-----------------------------------------------------------------------------------------------------------------------
print
print 'Scanning BL Data...'
for file in os.listdir(path):
    match = re.search(r'.*\.[pP][dD][fF]', file)
    if match:
        blFound= 'true'
        os.system("C:/Python27/Scripts/pdf2txt.py -o d:/bls.txt "+path+file)
        blFile = open("d:/bls.txt").read()
        #identifies if its a bill of lading or air waybill:
        if "BILL OF LADING" in blFile:
            #ok it is a bl from Maersk or KN?
            #now scans the file line by line looking for matches
            blFile = open("d:/bls.txt")
            for line in blFile:
                mBlNumber = re.search(r'^\d{9}\n$',line)
                mTotalCases = re.search(r'\d\s\s\d+\sC[aA]?[sS][eE]?', line) #sometimes it is written 'CASE' or 'CS'
                mGrossWeight = re.search(r'\w\s\s\d+\.*\d*\sKGS', line)
                mVolume = re.search(r'\w\s\s\d+\.*\d*\sCBM', line)
                mContainers = re.search(r'[A-Z]{4}\d{7}', line)
                if mBlNumber: blNumber = mBlNumber.group()[:-1]
                if mTotalCases:
                    casePosition = mTotalCases.group().find('C') #finds the position of leter 'C' in order not to copy it.
                    blCases.append(int(mTotalCases.group()[3:casePosition]))
                if mGrossWeight: blWeight.append(float(mGrossWeight.group()[3:-3]))
                if mVolume: blVolume.append(float(mVolume.group()[3:-3]))
                if mContainers: containers.append(line[:-13])
        else:
            #then if it is an airway bill
            #is it from panalpina or dhl?
            if "PANALPINA" in blFile:
                blFile = open("d:/bls.txt")
                for line in blFile:
                    mBlNumber = re.search(r'SZX\s\s\d{6}',line)
                    mTotalCases = re.search(r'TOTAL:\d+\s', line)
                    mGrossWeight = re.search(r'\d+\.?\d*K\s', line)
                    mVolume = re.search(r'VOLUME\s\s\s\s\d+\.?\d*\s', line)
                    if mBlNumber:
                        blNumber = mBlNumber.group()
                        blNumber = blNumber.replace('  ', '')
                    if mTotalCases: blCases.append(int(mTotalCases.group()[6:-1]))
                    if mGrossWeight: blWeight.append(float(mGrossWeight.group()[:-2]))
                    if mVolume: blVolume.append(float(mVolume.group()[10:-1]))
if blFound == 'true' and blNumber != '':     
    print "BL Number: %s, Total cases: %i, Total Gross Weight: %f, Total Volume: %f" %(blNumber, sum(blCases), sum(blWeight), sum(blVolume))
    print 'Cointainers:'
    for cont in containers:
        print cont
else:
    print 'BL/AWB not found!'
#look for discrepancies----------------------------------------------------------------------------------------------------------------------------
#if (cases - blCases != 0) or (gweight - blWeight!=0) or (volume - blVolume !=0):
if tcases != sum(blCases) or tgweight != sum(blWeight) or sum(volume)!= sum(blVolume):
    print
    print 'WARNING! Some discrepancies found between PLs and BL/AWB'
#create report loader--------------------------------------------------------------------------------------------------------------------------------
print
print 'Creating loader...'
try:
    template = openpyxl.load_workbook("d:/loadTemplate.xlsx")
    templateSheet = template.get_sheet_by_name("Sheet1")
    templateSheet.cell(row=2, column=10).value = fob
    templateSheet.cell(row=2, column=11).value = freight
    templateSheet.cell(row=2, column=12).value = insurance
    templateSheet.cell(row=2, column=13).value = total
    templateSheet.cell(row=2, column=7).value = ""
    for inv in invoice:
        if templateSheet.cell(row=2, column=7).value == "":
            templateSheet.cell(row=2, column=7).value = inv + " "
        else:
            templateSheet.cell(row=2, column=7).value = templateSheet.cell(row=2, column=7).value + inv + " "
    templateSheet.cell(row=2, column=1).value = plNum
    templateSheet.cell(row=2, column=14).value = tcases
    templateSheet.cell(row=2, column=15).value = tgweight
    templateSheet.cell(row=2, column=16).value = tvolume
    templateSheet.cell(row=2, column=20).value = blNumber
    templateSheet.cell(row=2, column=25).value = ''
    for cont in containers:
        if templateSheet.cell(row=2, column=25).value == '':
            templateSheet.cell(row=2, column=25).value = cont + ' '
        else:
            templateSheet.cell(row=2, column=25).value = templateSheet.cell(row=2, column=25).value + cont + ' '
    template.save("d:/loader.xlsx")
   
    print
    print 'Process complete.'
except:
    print 'WARNING! There was a problem writing the loader. Maybe the file loader.xlsx is open?'
raw_input ()
       

miércoles, 24 de septiembre de 2014

Python: Extraer datos de un archivo PDF usando PDFMiner

Lo primero logicamente es descargar e instalar la libreria PDFMiner

PDFMiner viene con una herramienta que se puede usar directamente en la linea de comados, hay que entrar a la carpeta que contiene el script pdf2txt.py, y ejecutarlo especificando primero el nombre del archivo de salida y luego el nombre del archivo pdf del que vamos a extraer, por ejemplo:

C:\Python27\Scripts>python pdf2txt.py -o d:/output.txt d:/BL.pdf

Esto crea un archivo de texto llamado output en el disco D:

Ahora si queremos utilizar este script dentro de otro script, se lo puede ejecutar usado os.system:

>>> import os
>>> os.system('C:\Python27\Scripts\pdf2txt.py -o d:/output.txt d:/BL.pdf')


Cabe recalcar que en este caso fue necesario especificar la ruta completa al script pdf2txt.py

lunes, 15 de septiembre de 2014

R: Formas de eliminar los valores NA

R viene con un data set incluido, llamado airquality:

> airquality
    Ozone Solar.R Wind Temp Month Day
1      41     190  7.4   67     5   1
2      36     118  8.0   72     5   2
3      12     149 12.6   74     5   3
4      18     313 11.5   62     5   4
5      NA      NA 14.3   56     5   5
6      28      NA 14.9   66     5   6
7      23     299  8.6   65     5   7
8      19      99 13.8   59     5   8
9       8      19 20.1   61     5   9
10     NA     194  8.6   69     5  10
11      7      NA  6.9   74     5  11
12     16     256  9.7   69     5  12
13     11     290  9.2   66     5  13
14     14     274 10.9   68     5  14
15     18      65 13.2   58     5  15
16     14     334 11.5   64     5  16
17     34     307 12.0   66     5  17
18      6      78 18.4   57     5  18
19     30     322 11.5   68     5  19
20     11      44  9.7   62     5  20
21      1       8  9.7   59     5  21
22     11     320 16.6   73     5  22
23      4      25  9.7   61     5  23
24     32      92 12.0   61     5  24
25     NA      66 16.6   57     5  25
26     NA     266 14.9   58     5  26
27     NA      NA  8.0   57     5  27
28     23      13 12.0   67     5  28
29     45     252 14.9   81     5  29
30    115     223  5.7   79     5  30
31     37     279  7.4   76     5  31
32     NA     286  8.6   78     6   1
33     NA     287  9.7   74     6   2
34     NA     242 16.1   67     6   3
35     NA     186  9.2   84     6   4
36     NA     220  8.6   85     6   5
37     NA     264 14.3   79     6   6
38     29     127  9.7   82     6   7
39     NA     273  6.9   87     6   8
40     71     291 13.8   90     6   9
41     39     323 11.5   87     6  10
42     NA     259 10.9   93     6  11
43     NA     250  9.2   92     6  12
44     23     148  8.0   82     6  13
45     NA     332 13.8   80     6  14
46     NA     322 11.5   79     6  15
47     21     191 14.9   77     6  16
48     37     284 20.7   72     6  17
49     20      37  9.2   65     6  18
50     12     120 11.5   73     6  19
51     13     137 10.3   76     6  20
52     NA     150  6.3   77     6  21
53     NA      59  1.7   76     6  22
54     NA      91  4.6   76     6  23
55     NA     250  6.3   76     6  24
56     NA     135  8.0   75     6  25
57     NA     127  8.0   78     6  26
58     NA      47 10.3   73     6  27
59     NA      98 11.5   80     6  28
60     NA      31 14.9   77     6  29
61     NA     138  8.0   83     6  30
62    135     269  4.1   84     7   1
63     49     248  9.2   85     7   2
64     32     236  9.2   81     7   3
65     NA     101 10.9   84     7   4
66     64     175  4.6   83     7   5
67     40     314 10.9   83     7   6
68     77     276  5.1   88     7   7
69     97     267  6.3   92     7   8
70     97     272  5.7   92     7   9
71     85     175  7.4   89     7  10
72     NA     139  8.6   82     7  11
73     10     264 14.3   73     7  12
74     27     175 14.9   81     7  13
75     NA     291 14.9   91     7  14
76      7      48 14.3   80     7  15
77     48     260  6.9   81     7  16
78     35     274 10.3   82     7  17
79     61     285  6.3   84     7  18
80     79     187  5.1   87     7  19
81     63     220 11.5   85     7  20
82     16       7  6.9   74     7  21
83     NA     258  9.7   81     7  22
84     NA     295 11.5   82     7  23
85     80     294  8.6   86     7  24
86    108     223  8.0   85     7  25
87     20      81  8.6   82     7  26
88     52      82 12.0   86     7  27
89     82     213  7.4   88     7  28
90     50     275  7.4   86     7  29
91     64     253  7.4   83     7  30
92     59     254  9.2   81     7  31
93     39      83  6.9   81     8   1
94      9      24 13.8   81     8   2
95     16      77  7.4   82     8   3
96     78      NA  6.9   86     8   4
97     35      NA  7.4   85     8   5
98     66      NA  4.6   87     8   6
99    122     255  4.0   89     8   7
100    89     229 10.3   90     8   8
101   110     207  8.0   90     8   9
102    NA     222  8.6   92     8  10
103    NA     137 11.5   86     8  11
104    44     192 11.5   86     8  12
105    28     273 11.5   82     8  13
106    65     157  9.7   80     8  14
107    NA      64 11.5   79     8  15
108    22      71 10.3   77     8  16
109    59      51  6.3   79     8  17
110    23     115  7.4   76     8  18
111    31     244 10.9   78     8  19
112    44     190 10.3   78     8  20
113    21     259 15.5   77     8  21
114     9      36 14.3   72     8  22
115    NA     255 12.6   75     8  23
116    45     212  9.7   79     8  24
117   168     238  3.4   81     8  25
118    73     215  8.0   86     8  26
119    NA     153  5.7   88     8  27
120    76     203  9.7   97     8  28
121   118     225  2.3   94     8  29
122    84     237  6.3   96     8  30
123    85     188  6.3   94     8  31
124    96     167  6.9   91     9   1
125    78     197  5.1   92     9   2
126    73     183  2.8   93     9   3
127    91     189  4.6   93     9   4
128    47      95  7.4   87     9   5
129    32      92 15.5   84     9   6
130    20     252 10.9   80     9   7
131    23     220 10.3   78     9   8
132    21     230 10.9   75     9   9
133    24     259  9.7   73     9  10
134    44     236 14.9   81     9  11
135    21     259 15.5   76     9  12
136    28     238  6.3   77     9  13
137     9      24 10.9   71     9  14
138    13     112 11.5   71     9  15
139    46     237  6.9   78     9  16
140    18     224 13.8   67     9  17
141    13      27 10.3   76     9  18
142    24     238 10.3   68     9  19
143    16     201  8.0   82     9  20
144    13     238 12.6   64     9  21
145    23      14  9.2   71     9  22
146    36     139 10.3   81     9  23
147     7      49 10.3   69     9  24
148    14      20 16.6   63     9  25
149    30     193  6.9   70     9  26
150    NA     145 13.2   77     9  27
151    14     191 14.3   75     9  28
152    18     131  8.0   76     9  29
153    20     223 11.5   68     9  30

Si quieres por ejemplo sacar la media de la variable "Ozone" te da error porque contiene valores NA:

> mean(airquality$ozone)
[1] NA
Warning message:
In mean.default(airquality$ozone) :
  argument is not numeric or logical: returning NA

Las dos maneras mas sencillas para eliminar esos NAs son:

> complete = na.omit(airquality)
> complete =  airquality[complete.cases(airquality), ]
Ambas producen un mismo resultado: Un data frame que no contiene ningun valor NA:

> complete
    Ozone Solar.R Wind Temp Month Day
1      41     190  7.4   67     5   1
2      36     118  8.0   72     5   2
3      12     149 12.6   74     5   3
4      18     313 11.5   62     5   4
7      23     299  8.6   65     5   7
8      19      99 13.8   59     5   8
9       8      19 20.1   61     5   9
12     16     256  9.7   69     5  12
13     11     290  9.2   66     5  13
14     14     274 10.9   68     5  14
15     18      65 13.2   58     5  15
16     14     334 11.5   64     5  16
17     34     307 12.0   66     5  17
18      6      78 18.4   57     5  18
19     30     322 11.5   68     5  19
20     11      44  9.7   62     5  20
21      1       8  9.7   59     5  21
22     11     320 16.6   73     5  22
23      4      25  9.7   61     5  23
24     32      92 12.0   61     5  24
28     23      13 12.0   67     5  28
29     45     252 14.9   81     5  29
30    115     223  5.7   79     5  30
31     37     279  7.4   76     5  31
38     29     127  9.7   82     6   7
40     71     291 13.8   90     6   9
41     39     323 11.5   87     6  10
44     23     148  8.0   82     6  13
47     21     191 14.9   77     6  16
48     37     284 20.7   72     6  17
49     20      37  9.2   65     6  18
50     12     120 11.5   73     6  19
51     13     137 10.3   76     6  20
62    135     269  4.1   84     7   1
63     49     248  9.2   85     7   2
64     32     236  9.2   81     7   3
66     64     175  4.6   83     7   5
67     40     314 10.9   83     7   6
68     77     276  5.1   88     7   7
69     97     267  6.3   92     7   8
70     97     272  5.7   92     7   9
71     85     175  7.4   89     7  10
73     10     264 14.3   73     7  12
74     27     175 14.9   81     7  13
76      7      48 14.3   80     7  15
77     48     260  6.9   81     7  16
78     35     274 10.3   82     7  17
79     61     285  6.3   84     7  18
80     79     187  5.1   87     7  19
81     63     220 11.5   85     7  20
82     16       7  6.9   74     7  21
85     80     294  8.6   86     7  24
86    108     223  8.0   85     7  25
87     20      81  8.6   82     7  26
88     52      82 12.0   86     7  27
89     82     213  7.4   88     7  28
90     50     275  7.4   86     7  29
91     64     253  7.4   83     7  30
92     59     254  9.2   81     7  31
93     39      83  6.9   81     8   1
94      9      24 13.8   81     8   2
95     16      77  7.4   82     8   3
99    122     255  4.0   89     8   7
100    89     229 10.3   90     8   8
101   110     207  8.0   90     8   9
104    44     192 11.5   86     8  12
105    28     273 11.5   82     8  13
106    65     157  9.7   80     8  14
108    22      71 10.3   77     8  16
109    59      51  6.3   79     8  17
110    23     115  7.4   76     8  18
111    31     244 10.9   78     8  19
112    44     190 10.3   78     8  20
113    21     259 15.5   77     8  21
114     9      36 14.3   72     8  22
116    45     212  9.7   79     8  24
117   168     238  3.4   81     8  25
118    73     215  8.0   86     8  26
120    76     203  9.7   97     8  28
121   118     225  2.3   94     8  29
122    84     237  6.3   96     8  30
123    85     188  6.3   94     8  31
124    96     167  6.9   91     9   1
125    78     197  5.1   92     9   2
126    73     183  2.8   93     9   3
127    91     189  4.6   93     9   4
128    47      95  7.4   87     9   5
129    32      92 15.5   84     9   6
130    20     252 10.9   80     9   7
131    23     220 10.3   78     9   8
132    21     230 10.9   75     9   9
133    24     259  9.7   73     9  10
134    44     236 14.9   81     9  11
135    21     259 15.5   76     9  12
136    28     238  6.3   77     9  13
137     9      24 10.9   71     9  14
138    13     112 11.5   71     9  15
139    46     237  6.9   78     9  16
140    18     224 13.8   67     9  17
141    13      27 10.3   76     9  18
142    24     238 10.3   68     9  19
143    16     201  8.0   82     9  20
144    13     238 12.6   64     9  21
145    23      14  9.2   71     9  22
146    36     139 10.3   81     9  23
147     7      49 10.3   69     9  24
148    14      20 16.6   63     9  25
149    30     193  6.9   70     9  26
151    14     191 14.3   75     9  28
152    18     131  8.0   76     9  29
153    20     223 11.5   68     9  30

Ahora sí puedo sacar la media de "Ozone" en aquellas observaciones en que no existia ningun NA

> mean(complete$Ozone)
[1] 42.0991

Aunque hay una forma mas directa de sacar la media sin crear un data frame de valores completos. Se puede utilizar el data frame 'en bruto' solo espeficando que se deben omitir los valores NA al momento del calculo:

> mean(na.omit(airquality)$Ozone)
[1] 42.0991
Sin embargo hay observaciones que sí tienen valores en "Ozone" pero que quizas no tengan valores en otras variables, por lo que na.omit() y complete.cases() van a dear fuera a toda la fila.

Para calcular la media con todos los valores de Ozone, asi falten valores en otras variables, se realiza de la siguiente manera:

> mean(airquality$Ozone, na.rm = TRUE)
[1] 42.12931


domingo, 14 de septiembre de 2014

R: Tercer proyecto de Coursera "Correlation"

El tercero consistía en una funcion para crean un listado con las correlaciones entre dos variables en cada archivo de un directorio, con un umbral de casos completos.

corr <- function(directory, threshold = 0) {
 
  file_list = list.files(directory)
  found = FALSE
 
  for (file in file_list){
    current_file = read.csv(paste(directory,"/", file, sep =""))
    observed_cases = sum(complete.cases(current_file))
    if (observed_cases >= threshold) {
      found = TRUE
      data_frame = na.omit(current_file)
      if (!exists("cor_vector")){
        cor_vector = cor(data_frame$sulfate, data_frame$nitrate)
      }else{
        temp_vector = cor(data_frame$sulfate, data_frame$nitrate)
        cor_vector = c(cor_vector, temp_vector)
        rm(temp_vector)
      }
 
    }
   
  }
  if(found==TRUE){cor_vector = cor_vector[-1]}
 
}

R: Segundo proyecto de Coursera 'Complete'

El segundo deber consistía en crea una función que genere un data frame indicando cuantas observaciones completas contiene cada archivo de un directorio:

complete = function(directory, iden=1:332){
  file_list = list.files(directory)
  for (file in file_list) {
    x = read.csv(paste(directory,"/",file, sep =""))
    if (x[1,4] %in% iden){
      monitor = x[1,4]
      complete_cases = sum(complete.cases(x))   
      if (!exists("data_frame")){
        data_frame = data.frame(id=monitor, nobs = complete_cases) 
      } else {
        temp_data_frame = data.frame(id=monitor, nobs = complete_cases)
        data_frame = rbind(data_frame, temp_data_frame)
        rm(temp_data_frame)
      }
    }
  }
 
  for (value in iden){
    for (rows in seq(nrow(data_frame))){
      if (data_frame[rows,1] == value){
        if (!exists("monitor_frame")){
          monitor_frame = subset(data_frame, id == value)
        }else{
          temp_monitor_frame = subset(data_frame, id==value)
          monitor_frame = rbind(monitor_frame, temp_monitor_frame)
          rm(temp_monitor_frame)
        }
        break
      }
    }
  }
  print(monitor_frame)
}

R: Proyecto de Coursera 'Pollutantmean'

Este es el primer deber, así lo hice:

pollutantmean = function(directory, pollutant, id = 1:332){
 
  file_list = list.files(directory)
 
  for (file in file_list) {
    if (!exists("data_frame")) {
      data_frame = read.csv(paste(directory,"/", file, sep = ""), header= TRUE)
       
    } else {
      temp_data = read.csv(paste(directory,"/", file, sep=""), header = TRUE)
      data_frame = rbind(data_frame, temp_data)
      rm(temp_data)
           
    }
   
  }
 
  good = complete.cases(data_frame)
  complete_data_frame = data_frame[good, ]
 
  monitor_filter = subset(complete_data_frame, ID %in% id)
 
  mean(monitor_filter[, pollutant])
}

domingo, 7 de septiembre de 2014

Python: Crear un listado con cada letra de una palabra

>>> #primero creo la variable con la  cadena de texto:

>>> ruben = "ruben dario torres macias"
>>> ruben
'ruben dario torres macias'


>>> #ahora remuevo los espacios

>>> ruben =ruben.replace(" ", "")
>>> ruben
'rubendariotorresmacias'


>>> #ahora creo una lista vacia donde almacenaré las letras:

... letras =[]

>>> #para leer cada letra hago un subset en cada posicion de la variable 'ruben'

... for l in range(0, len(ruben)):
...     letras.append(ruben[l])
...
>>> letras
['r', 'u', 'b', 'e', 'n', 'd', 'a', 'r', 'i', 'o', 't', 'o', 'r', 'r', 'e', 's', 'm', 'a', 'c', 'i', 'a', 's']

martes, 2 de septiembre de 2014

Python: Como contar el numero de veces que un elemento aparece en una lista. Funcion collections.Counter()

Tengo un listado como por ejemplo:

1
2
3
4
4
5
6
6
7
8
9
9
10
11
12
12
12
13
14
14
15
15
15

Deseo contar cuantas veces se ha repetido cada numero:

Mi archivo se llama dictionary.txt, pimero creo una lista:

>>> lista = [item for item in open('dictionary.txt').readlines()]
>>> lista
['1\n', '2\n', '3\n', '4\n', '4\n', '5\n', '6\n', '6\n', '7\n', '8\n', '9\n', '9
\n', '10\n', '11\n', '12\n', '12\n', '12\n', '13\n', '14\n', '14\n', '15\n', '15
\n', '15']





Sin embargo al final de cada lista me aparece un simbolo de final de linea, el cual elimino de la siguiente manera:

>>> for item in lista:
...     if '\n'in item:
...             lista[lista.index(item)]=item.replace('\n', '')
...
>>> lista
['1', '2', '3', '4', '4', '5', '6', '6', '7', '8', '9', '9', '10', '11', '12', '
12', '12', '13', '14', '14', '15', '15', '15']


Ahora lo maravilloso, en el modulo collections existe una funcion llamada Counter, que crea un diccionario con los elementos de una lista y cuenta el numero de ocurrencias:

>>> diccionario= collections.Counter(lista)
>>>
>>> diccionario
Counter({'12': 3, '15': 3, '14': 2, '4': 2, '6': 2, '9': 2, '11': 1, '10': 1, '1
3': 1, '1': 1, '3': 1, '2': 1, '5': 1, '7': 1, '8': 1})


Si no te gusta que al comienzo aparezca la palabra Counter, pues conviertelo a diccionario con la funcion dict()

>>> diccionario = dict(diccionario)
>>> diccionario
{'11': 1, '10': 1, '13': 1, '12': 3, '15': 3, '14': 2, '1': 1, '3': 1, '2': 1, '
5': 1, '4': 2, '7': 1, '6': 2, '9': 2, '8': 1}
>>>

miércoles, 27 de agosto de 2014

VBA Excel: Como realizar un proceso en todos los controles de una User Form

La propiedad Controls de la User Form es una coleccion de los controles, y se identifica cada tipo de control con la funcion TypeName():

Esta es mi forma:


Y En este ejemplo lo que hago es borrar el contenido de cada control:

'Loop through all control looking for the typename TextBoxes
For Each cname In expensesForm.Controls
    If TypeName(cname) = "TextBox" Then
        cname.Value = ""
    End If
Next cname

'now loop controls looking for checkBoxes with set value true

For Each cname In expensesForm.Controls
    If TypeName(cname) = "CheckBox" Then
        cname.Value = False
    End If
Next cname

End Sub


lunes, 25 de agosto de 2014

Linea de comandos: La forma mas rapida de buscar un tipo de archivos y copiarlos de un directorio a otro.


Digamos que quiero un listado de todos los archivos con macros en mi directorio "rubenbk" y quiero copiarlos al directorio "rubentest"

Par ver el listado de los archivos puedo hacer un DIR con el swtich /S para que busque tambien en las subcarpetas.

D:\>dir "d:\rubenbk\*.xlsm" /s

Ahora para copiar esos archivos, puedo hacerlo con el comando XCOPY "origen" "destino"

D:\>xcopy "d:\rubenbk\*.xlsm" "d:\rubentest" /s

Nuevamente el switch /S permite que copie desde cada una de las subcarpetas.

El problema con xcopy es que copia los archivos pero mantiene la estructura de las subcarpetas, es decir copia los archivos y las carpetas que los contienen.

Si quiero solo los archivos encontré algo mas complicado pero efectivo, con un for command:

D:\>for /r "d:\rubenbk" %G in ("*.xlsm") do copy %G "d:\rubentest"

La /r indica que va a buscar dentro de cada carpeta y subcarpeta del directorio "d:\rubenbk"
%G es el nombre de la variable que contendrá cada nombre de archivo encontrado
in ("*.xlsm") representa el set de archivos que termina con la extension xlsm.
do es el comando que indica la accion que se va a realizar con cada variable %G
copy %G "d:\rubentest" indica que se copia cada archivo a la carpeta de destino.


domingo, 24 de agosto de 2014

Python: Eliminar duplicados de una lista.

Para esto sirven los SETS. Son estructuras de datos que no permiten el ingreso de elementos duplicados.

#aqui el archivo con el listado de contratos
contractsList = open('/users/eljayan/documents/python/contracts.txt')

#aqui el archivo donde escribiré los contratos únicos.
uniqueContracts = open('/users/eljayan/documents/python/unique.txt', 'w')

#primero creo un set vacio
cList = set()

#luego leo el archivo, el metodo read devuelve una sola cadena de texto que contiene todo.
contractsList = contractsList.read()

#separo la cadena de texto para poder tener un listado con cada nombre de contrato.
contractsList = contractsList.split()

#por cada nombre de contrato, voy agregando al set. Si el nombre ya existe, simplemente lo ignora.
for line in contractsList:
    cList.add(line)

#ahora escribo en el segundo archivo de la lista el contenido del set con los nombres unicos.
for contract in cList:
    uniqueContracts.write(contract+'\n')

Python: Graficos con Turtle


Es solo un juego:


import turtle

ruben = turtle.Turtle()

for angle in range(36):
        for times in range(4):
                ruben.forward(200)
                ruben.right(90)
        ruben.right(10)

Y el resultado es:


sábado, 23 de agosto de 2014

Linea de comandos: Como editar la variable PATH

Sirve para ejecutar Python.exe desde cualquier directorio en la linea de comandos. El bash buscará el ejecutable en todos los directorios especificados en la variable PATH

Por ejemplo si digito python en la linea de comandos, rebota este error:

C:\>python
"python" no se reconoce como un comando interno o externo,
programa o archivo por lotes ejecutable.

Con set path puedo agregar el directorio que contiene python.exe a la variable:

C:\>set PATH= %PATH%;C:\Python27

Ahora si, al digitar python en la linea de comandos, se abre el interprete:

C:\>python
Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>>

viernes, 22 de agosto de 2014

miércoles, 13 de agosto de 2014

Python: Como remover espacios o caracteres no deseados de una linea.

Tengo un archivo del cual extraje las lineas que mencionaban "Serial Number" y el resultado fue este:

inputFile = open("D:/tipos de tarjetas.txt")
outputFile = open("D:/output.txt","w")

for line in inputFile:
    if "Serial Number" in line:
        serial = line
        outputFile.write(serial)

El output es:

      Serial Number  =  210231626710D5000030
      Serial Number  =  210231626710B8000038
      Serial Number  =  210231626710B8000058
      Serial Number  =  210231626710B8000115

Quiero dejar solo los numeros de serial.

inputFile = open("D:/tipos de tarjetas.txt")
outputFile = open("D:/output.txt","w")

for line in inputFile:
    if "Serial Number" in line:
        serial = line
        #primero elimino la palabra serial
        serial= serial.replace("Serial Number", "")
        #luego voy por el signo igual
        serial = serial.replace("=", "")
        #termino eliminando todos los espacios.
        serial = serial.replace(" ", "")
        outputFile.write(serial)

El resultado final:

210231626710D5000030
210231626710B8000038
210231626710B8000058
210231626710B8000115

martes, 12 de agosto de 2014

Python: Cambiando el formato de fecha en una celda usando Openpyxl


Ha sido tan falcil como crear el objecto celda y aplicar la propiedad .number_format = "dd-mm-yyy" o como quieras.

#pega la fecha del contrato
 billingReportSheet.cell(row=n, column=3).value = contractsReport.sheet_by_index(0).cell_value(statRow,15)

#si es una fecha, se copiará como "4562763"

#cambia el formato
billingReportSheet.cell(row=n, column=3).number_format = "dd-mm-yyyy"

viernes, 8 de agosto de 2014

Python: Como ejecutar un programa de Python en una computadora que no tiene Python.


Encontre un tutorial excelente

Lo primero es instalar la librería py2exe.

Luego, básicamente lo que se debe hacer es crear un script llamado setup.py en el mismo directorio donde se encuentre el script principal. Setup.py debe contener los siguiente:

from distutils.core import setup
import py2exe
setup(console=['nombreDelPrograma.py'])

Luego con la linea de comandos se debe ingresar a la carpeta que contiene el script y ejecutar:

C:\python setup.py py2exe

Esta acción crea un una carpeta "build" y una "dist" en el directorio del script.

La carpeta build se la puede borrar. La carpeta dist es la importante. Esta es la que contiene el ejecutable del programa.

Ahora solo hay que copiar la carpeta dist en la computadora donde deseamos que se ejecute el programa. El ejecutable siempre debe estar dentro de la carpeta dist, de lo contrario no funcionará.

Para mayor facilidad de uso es buena idea crear un acceso directo para el ejecutable en el escritorio.

VBA Excel: Como saber si un array está vacio y como saber si un valor está ya dentro de un array.

Si tengo un listado de contratos repetidos en una columna, pero solo quiero el resumen de los mismos:

CONTRACT 4
CONTRACT 1
CONTRACT 2
CONTRACT 1
CONTRACT 3
CONTRACT 1
CONTRACT 3
CONTRACT 1
CONTRACT 5
CONTRACT 1
CONTRACT 1
CONTRACT 4
CONTRACT 1
CONTRACT 5
CONTRACT 5
CONTRACT 3
CONTRACT 3

Asigno cada celda a un array, solo agrego elementos al array si no constan ya dentro del mismo:

Sub create()

'Declaro un array en blanco y un contador para ir llenandolo.
Dim contracts() As String
Dim n As Integer
n = 0

'Por cada celda del rango
For Each cell In Range("a1", "a" & Range("a1").End(xlDown).Row)
'Si la longitud del array es 0, entonces agrego la celda.
    If Len(Join(contracts)) < 1 Then
        ReDim Preserve contracts(n)
        contracts(n) = cell.Value
        n = n + 1
'Llena y pasa a la siguiente celda del rango:
        GoTo cont:
    Else
'Testea si el valor de la celda ya ha existe dentro del array, la funcion la copié de un foro.
'Si el valor no existe, agrega la celda al array.
        If Not IsInArray(cell.Value, contracts) Then
            ReDim Preserve contracts(n)
            contracts(n) = cell.Value
            n = n + 1
        End If
    End If
cont:
Next cell

'Ahora a poblar otra columna con los contratos encontrados. 
upper = n   'es la fila maxima a pegar, que equivale al contador de los arrays ingresados
n = 0 'reinicio el contador para ir obteniedo los valores del array y pegarlos 

'Pego los valores
For brow = 1 To upper
    Range("B" & brow).Value = contracts(n)
    n = n + 1
Next brow

End Sub

---------esta es la funcion que usé para testear si un valor se encontraba dentro de un array---------
Function IsInArray(stringToBeFound As String, arr As Variant) As Boolean
  IsInArray = (UBound(Filter(arr, stringToBeFound)) > -1)
End Function
Nota: Estoy creando un tutorial para aprender a utilizar VBA en la oficina. La pagina es www.macroreportes.com eventualmente ire agregando mas secciones, por lo que si quieres seguir el curso seria buena idea registrar tu email en la pagina para recibir las notificaciones cuando suba un nuevo post.

martes, 5 de agosto de 2014

VBA Excel: Como Insertar objetos en hoja de calculo.


Sub InsertObject()
Dim cell As Range
Dim fname As String
Dim filepath As String
Dim file As OLEObjects

For Each cell In Range("a2: a47")
    cell.Offset(0, 2).Select
    fname = cell.Text
    filepath = "C:\Users\Ruben Torres\Desktop\Adam\" & fname & ".xlsx"
       
     ActiveSheet.OLEObjects.Add(filename:=filepath, Link:=False, _
       DisplayAsIcon:=True, IconFileName:= _
       "C:\Windows\Installer\{AC76BA86-7AD7-1033-7B44-AA1000000001}\PDFFile_8.ico", IconIndex:=0, _
       IconLabel:=fname).Select
   
Next cell

End Sub

domingo, 3 de agosto de 2014

Python para Excel: Mi primer Programa.

Sirve para extraer la información desordenada de códigos, descripciones y precios de entre mas de 1000 archivos que tengo en una carpeta:



import openpyxl, xlrd, os.path, re, time, datetime

#first, create a workbook that will contain the merged info.
database = openpyxl.Workbook()

#now create a new worksheet
databaseSheet = database.create_sheet(0)


#rename worksheet.
databaseSheet.title = "Database"

#first and second lines in the worksheet:
databaseSheet.cell(row=1,column=1).value = 'PRICE RECORD OF HUAWEI PRODUCTS IMPORTED FROM 2009'
databaseSheet.cell(row=2,column=1).value ='Part Number'
databaseSheet.cell(row=2,column=2).value = 'Description'
databaseSheet.cell(row=2,column=3).value = 'Quantity'
databaseSheet.cell(row=2,column=4).value = 'Unit Price'
databaseSheet.cell(row=2,column=5).value = 'Source File'
databaseSheet.cell(row=2,column=6).value = 'Date'

rowPaste = 3 #the first row free to start pasting the info
scannedFiles = 0
pathNames = ["d:/rubenbk/confirmar facturas/","d:/rubenbk/database/"]

for path in pathNames:
    #list all files to be searched
    for root, folders, files in os.walk(path):
            for file in files:
                foundColumns = 0 #will count the columns we're looking on each row
                #test if it is an excel file using regular expressions
                match = re.search(r'[^\?]*\w+\.xl\w+', file)
                #if the match object is true: 
                if match:
                    print file
                    #opens each file in folder for reading
                    currentFile = xlrd.open_workbook(os.path.join(root,file))
                    #gets the first sheet for reading
                    currentSheet = currentFile.sheet_by_index(0) #gets the first sheet.
                    #starts iteration on each row and cell in the active sheet
                    #in order to find the columns we will extract the info from.
                    foundColumns = 0
                    for row in range(currentSheet.nrows):
                        for col in range(currentSheet.ncols):
                            #looks for the pattern of Unit Price
                            matchPrice = re.search(r'^[Uu][\w\.\s]*[Pp][Rr][Ii][Cc][Ee].*', unicode(currentSheet.cell_value(row,col)))
                            #looks for part number
                            matchPart = re.search(r'[Pp][Aa][Rr][Tt]\s[Nn][\s\S\W.]*', unicode(currentSheet.cell_value(row,col)))
                            #looks for description
                            matchDescription = re.search(r'[Dd][Ee][Ss][Cc][Rr][Ii][Pp][Tt][Ii][Oo][Nn]', unicode(currentSheet.cell_value(row,col)))
                            #looks for quantity
                            matchQty = re.search(r'[Qq][^Ll\s]*[Tt][Yy]', unicode(currentSheet.cell_value(row,col)))
                            #if any column was found, it adds to the foundColumns counter.
                            if matchPart:
                                #print "Part matched"
                                #print matchPart.group()
                                partCol = col
                                foundColumns +=1
                            if matchDescription:
                                #print 'Description matched'
                                #print matchDescription.group()
                                descriptionCol = col
                                foundColumns +=1
                            if matchQty:
                                #print 'Qty matched'
                                #print matchQty.group()
                                qtyCol = col
                                foundColumns +=1
                            if matchPrice:
                                #print 'Price matched'
                                #print matchPrice.group()
                                priceCol = col
                                foundColumns +=1
                        #if we found the four columns in the searched row:
                        #if foundColumns > 1: print foundColumns
                        if foundColumns == 4:
                            #print "found 4 columns!"
                            scannedFiles +=1
                            #we start getting the info from the rows below the one were we found the 4 variables
                            for rowCopy in range(row+1, currentSheet.nrows): #fromw the next row till the last in this document.
                                partValue = currentSheet.cell_value(rowCopy,partCol)
                                descValue = currentSheet.cell_value(rowCopy, descriptionCol)
                                qtyValue = currentSheet.cell_value(rowCopy, qtyCol)
                                priceValue = currentSheet.cell_value(rowCopy, priceCol)
                                #now we start writing the info in the database:
                                #if not currentSheet.cell_type(rowCopy,qtyCol) in (xlrd.XL_CELL_BLANK, xlrd.XL_CELL_EMPTY):
                                #if not (currentSheet.cell_type(rowCopy,partCol) or currentSheet.cell_type(rowCopy,qtyCol)
                                #or currentSheet.cell_type(rowCopy,descriptionCol) or currentSheet.cell_type(rowCopy,priceCol)) in (xlrd.XL_CELL_BLANK, xlrd.XL_CELL_EMPTY):
                                #if not (currentSheet.cell_value(rowCopy,partCol)=='' or currentSheet.cell_value(rowCopy,qtyCol) == ''
                                #or currentSheet.cell_value(rowCopy,descriptionCol)== '' or currentSheet.cell_value(rowCopy,priceCol) == ''):
                                if not (currentSheet.cell_value(rowCopy,qtyCol) == ''
                                or currentSheet.cell_value(rowCopy,descriptionCol)== '' or currentSheet.cell_value(rowCopy,priceCol) == ''):

                                    databaseSheet.cell(row=rowPaste,column= 1).value = partValue
                                    databaseSheet.cell(row=rowPaste,column= 2).value = descValue
                                    databaseSheet.cell(row=rowPaste,column= 3).value = qtyValue
                                    databaseSheet.cell(row=rowPaste,column= 4).value = priceValue
                                    databaseSheet.cell(row=rowPaste,column= 5).value = file
                                    databaseSheet.cell(row=rowPaste,column= 6).value = time.strftime('%d-%m-%Y',time.gmtime(os.path.getctime(os.path.join(root,file))))
                                    rowPaste +=1
                            break #we break the second for loop because it is now unnecessary.
                        else:
                            foundColumns = 0
                            continue
print
print "Total scanned files: %d" %scannedFiles
print
print 'Formatting database...'
print
for rowFinal in range(3,databaseSheet.get_highest_row()):
    fileValue = str(databaseSheet.cell(row=rowFinal, column = 5).value)
    if 'HS code' in fileValue:
        for columnFinal in range(1, 6):
            databaseSheet.cell(row=rowFinal, column=columnFinal).value =  databaseSheet.cell(row=rowFinal + 1, column=columnFinal).value
print 'Saving database...'    
print
database.save('D:/rubenbk/reports/pricesDatabase.xlsx')
print 'Done.'