简体   繁体   中英

Need to take data from text file to spreadsheet for analysis

I am working with data which I get in text files, and which has to be subsequently analysed. I'm currently using Excel for this task. The original file looks like this:

Contact Angle (deg)     86.20
Wetting Tension (dy/cm)     4.836
Wetting Tension Left (dy/cm)    39.44
Wetting Tension Right (dy/cm)   39.44
Base Tilt Angle (deg)       0.00
Base (mm)           1.6858
Base Area (mm2)         2.2322
Height (mm)         0.7888
Tip Width (mm)          0.9707
Wetted Tip Width (mm)       0.9581
Sessile Volume (ul)     1.1374
Sessile Surface Area (mm2)  4.1869
Contrast (cts)          245
Sharpness (cts)         161
Black Peak (cts)        10
White Peak (cts)        255
Edge Threshold (cts)        111
Base Left X (mm)        4.138
Base Right X (mm)       5.821
Base Y (mm)         2.980
RMS Fit Error (mm)      3.545E-3
@1600

I don't need the majority of this information, and for now, all I need is the Contact Angle at the top, and the time (prefixed by the '@' at the bottom). At the moment, I have a script which extracts the information I need and creates another text file for easy reading. The code used is below:

infile = "in.txt"
outfile = "newout.out"
measure_time = ""
with open(infile) as f, open(outfile, 'w') as f2:
    for line in f:
        if line.split():
            if line.split()[0] == "Contact":
                contact_angle = line.split()[-1].strip()
                f2.write("Contact Angle (deg): " + contact_angle + '\n')
            if line.split()[0][0] == '@':
                for i in range(1,5):
                    measure_time += (line.split()[0][i])
                f2.write("Measured at: " + measure_time[:2] + ":" + measure_time[2:] + '\n')
            measure_time = ""
        else:
            continue

What I am looking for is a way to get my data nicely formatted in a spreadsheet for easy analysis. I would like the angles in the same row, in adjoining cells, and the measurement time in the cells below that, but I'm unsure what the best way to go about this is.

Can anyone with some more Python experience help me here?

EDIT: The image here shows what I tried to explain (poorly) above. 我想要实现的样本

EDIT2: The solution posted below by @RonRosenfeld works, but I would still prefer to have a Python solution for this problem, as stated earlier. As I have no previous experience with Excel VBA, I would rather use something familiar to me.

I would just read the original file or files into Excel, selecting only those lines that begin with the Contact Angle, or @ token. I'm not sure how much error checking you need to do. The following assumes that you will select multiple files, and that each file is formatted as you demonstrated in your original data. It will output the angles in row 1, and the corresponding times in row 2. It does NOT check for proper formatting; or that every Angle has a corresponding Time.

It also does NOT test and will give an error, if you only select one file. That capability can be added, if necessary.

EDIT: modified to account for either TAB or SPACE as the separator; also added code to clear worksheet and autofit the columns

It should also be easy to modify if you want to select additional parameters.

    Option Explicit
'Set Reference to Microsoft Scripting Runtime
Sub GetDataFromTextFiles()
    Dim FSO As FileSystemObject
    Dim TS As TextStream
    Dim F As File
    Dim sLines As Variant
    Dim I As Long, J As Long
    Dim sFilePath
    Dim S As String
    Dim vLines() As Variant
    Dim rExtract As Range
'Hard Coded here but could also use a
'User form to select multiple lines
vLines = Array("@", "Contact Angle")
Set rExtract = [b3]
Cells.Clear

[a3] = "Contact Angle (deg)"
[a4] = "Measured At"

sFilePath = Application.GetOpenFilename("Text Files (*.txt), *.txt", MultiSelect:=True)
Set FSO = New FileSystemObject

For J = LBound(sFilePath) To UBound(sFilePath)
    Set TS = FSO.OpenTextFile(sFilePath(J), ForReading)

    Do Until TS.AtEndOfStream = True
    S = Trim(Replace(TS.ReadLine, Chr(9), Chr(32)))
        For I = 0 To UBound(vLines)
            If InStr(1, S, vLines(I)) = 1 Then
                Select Case I
                    Case 0 '@
                        With rExtract(2, 1)
                            .Value = TimeSerial(Int(Mid(S, 2) / 100), Mid(S, 2) Mod 100, 0)
                            .NumberFormat = "hh:mm"
                        End With
                    Case 1  '@
                        rExtract(1, 1) = Mid(S, InStrRev(S, " ") + 1)
                        'advance to next column after outputting angle
                        Set rExtract = rExtract(1, 2)
                End Select
            End If
        Next I
    Loop
Next J

Cells.EntireColumn.AutoFit

End Sub

Here is another macro that does NOT require setting a reference to Microsoft Scripting Runtime. It does not use the FileSystemObject, but rather uses built-in VBA routines to read the file. I have been told that it will run more quickly, but I've not tested it myself. In addition, there could be issues with certain types of data, but they do not seem to exist in your files, and it runs fine on your sample.

Option Explicit
Sub GetDataFromTextFiles()
    Dim sLines As Variant
    Dim I As Long, J As Long
    Dim sFilePath
    Dim S As String
    Dim vLines() As Variant
    Dim rExtract As Range
'Hard Coded here but could also use a
'User form to select multiple lines
vLines = Array("@", "Contact Angle")
Set rExtract = [b3]
Cells.Clear

[a3] = "Contact Angle (deg)"
[a4] = "Measured At"

sFilePath = Application.GetOpenFilename("Text Files (*.txt), *.txt", MultiSelect:=True)
For J = LBound(sFilePath) To UBound(sFilePath)
    Open sFilePath(J) For Input As #1
    Do While Not EOF(1)
    Input #1, S
    S = Trim(Replace(S, Chr(9), Chr(32)))
        For I = 0 To UBound(vLines)
            If InStr(1, S, vLines(I)) = 1 Then
                Select Case I
                    Case 0 '@
                        With rExtract(2, 1)
                            .Value = TimeSerial(Int(Mid(S, 2) / 100), Mid(S, 2) Mod 100, 0)
                            .NumberFormat = "hh:mm"
                        End With
                    Case 1
                        rExtract(1, 1) = Mid(S, InStrRev(S, " ") + 1)
                        'advance to next column after outputting angle
                        Set rExtract = rExtract(1, 2)
                End Select
            End If
        Next I
    Loop
    Close #1
Next J

Cells.EntireColumn.AutoFit

End Sub

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM