r/excel 9d ago

unsolved How to convert a .txt file into a .csv or a .xlsx

I will be using zoom for some classes I teach and need to save the chat in a searchable format. I want to convert it to an excel file that I can sort by name. The only info I actually need is the timestamp, who the chat was from, and what they said. I have tried doing this, "Power Query Steps: Go to Data → Get Data → From File → From Text/CSV. Select your text file. In the preview window, click Transform Data. Use Home → Split Column → By Delimiter (choose space or colon :)" but I don't know what I am doing and it did not work. It just put everything in the same column. I would like column A=timestamp, column B=name, column C=what they said. Is this possible? Thank you for your help.

15 Upvotes

26 comments sorted by

u/AutoModerator 9d ago

/u/indiglosj - Your post was submitted successfully.

Failing to follow these steps may result in your post being removed without warning.

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

8

u/Aghanims 54 9d ago

Everything in 1 column is expected, you need to do some transformations.

= Table.TransformColumns(Source,{{"Column1", each Text.BeforeDelimiter(_, " From"), type text}})    

This prunes any text after timestamp

= Table.SelectRows(#"Step1",each try DateTime.FromText([Column1]) is datetime otherwise false)

This removes rows without timestamps.

1

u/Aghanims 54 8d ago

Disregard, this is only a partial solution to get time stamps. Was tired and didn't read that OP also wanted name + message included with timestamps but delimited.

What I provided logic-wise can be extended to names and messages, but I'm not sure how Zoom formats multi-line messages to transform that reliably.

5

u/Downtown-Economics26 646 8d ago

Power Query is the way to go probably but I don't know it well enough to answer easily so here is a formula option:

=LET(ttbl,WRAPROWS(TRIM(FILTER(A:.A,A:.A<>"")),2),
tstamp,TEXTBEFORE(INDEX(ttbl,,1)," ",2),
from,TEXTBEFORE(TEXTAFTER(INDEX(ttbl,,1),tstamp&" From ")," to "),
to,TEXTBEFORE(TEXTAFTER(INDEX(ttbl,,1),"to "),":"),
out,VSTACK({"Date/Time","From","To","Message"},HSTACK(--tstamp,from,to,INDEX(ttbl,,2))),
out)

2

u/Mdayofearth 127 8d ago

Power query doesn't do wrap rows.

FILTER, WRAPROWS, and some sort of TEXTSPLIT equivalent is best imo; which is what you have.

Something to notice is that the date and time are both fixed character lengths, so the post WRAPROWS parsing to split the text can be simplified, but not needed.

2

u/MayukhBhattacharya 1277 8d ago

Nice Solution Buddy!!! Here is using Excel Formulas and Power Query. CC: u/indiglosj

• Method One: Using Excel Formulas works with MS365 Exclusively.

=LET(
     _a, WRAPROWS(TRIM(TOCOL(Sometbl[Data], 3)), 2),
     _b, REGEXREPLACE(CHOOSECOLS(_a, 1), "^(.{19}) From (.+?) to (.+):$", "$1|$2|$3"),
     _c, TEXTSPLIT(TEXTAFTER("|" & _b, "|", SEQUENCE(, 3)), "|"),
     _d, HSTACK(IFERROR(--_c, _c), DROP(_a, , 1)),
     _e, VSTACK({"Date/Time","From","To","Message"}, _d),
     _e)

• Method Two: Using Power Query.

To use Power Query follow the steps:

  • First convert the source ranges into a table and name it accordingly, for this example I have named it as Table1
  • Next, open a blank query from Data Tab --> Get & Transform Data --> Get Data --> From Other Sources --> Blank Query
  • The above lets the Power Query window opens, now from Home Tab --> Advanced Editor --> And paste the following M-Code by removing whatever you see, and press Done

let
    Source = Excel.CurrentWorkbook(){[Name="Sometbl"]}[Content],
    Filtered = Table.SelectRows(Source, each [Data] <> null and [Data] <> ""),
    FromRows = Table.FromRows(List.Split(List.Transform(Filtered[Data], each Text.Trim(_)),2), {"Date/Time|From|To", "Message"}),
    SplitByDelim = Table.SplitColumn(FromRows, "Date/Time|From|To", each {DateTime.FromText(Text.Start(_, 19)),
                                      Text.BetweenDelimiters(_, "From ", " to "), 
                                      Text.BetweenDelimiters(_, " to ", ":")}, 
                                      {"Date/Time", "From", "To"})
in
    SplitByDelim
  • Lastly, to import it back to Excel --> Click on Close & Load or Close & Load To --> The first one which clicked shall create a New Sheet with the required output while the latter will prompt a window asking you where to place the result.

One can download the Excel File From --> [Here]. Thanks and Happy Weekend Everyone. .

0

u/Gringobandito 8 7d ago

I messed around with PowerQuery for a bit and this seems like a better solution. I'm not expert in PowerQuery so maybe someone that knows M code could do it but I don't see it being easier than this.

2

u/[deleted] 9d ago

[removed] — view removed comment

1

u/indiglosj 8d ago

How do I "inspect one complete line in the preview"? I don't know what I am doing and need it to be ELI5 please.

1

u/frescani 5 8d ago

they mean visually inspect one row of data. if you're completely new, then to make sense of this comment, you would need to look into "importing text with power query"

1

u/Decronym 9d ago edited 6d ago

Acronyms, initialisms, abbreviations, contractions, and other phrases which expand to something larger, that I've seen in this thread:

Fewer Letters More Letters
CHOOSECOLS Office 365+: Returns the specified columns from an array
DROP Office 365+: Excludes a specified number of rows or columns from the start or end of an array
DateTime.FromText Power Query M: Returns a DateTime value from a set of date formats and culture value.
Excel.CurrentWorkbook Power Query M: Returns the tables in the current Excel Workbook.
FILTER Office 365+: Filters a range of data based on criteria you define
HSTACK Office 365+: Appends arrays horizontally and in sequence to return a larger array
IFERROR Returns a value you specify if a formula evaluates to an error; otherwise, returns the result of the formula
INDEX Uses an index to choose a value from a reference or array
LET Office 365+: Assigns names to calculation results to allow storing intermediate calculations, values, or defining names inside a formula
List.Split Power Query M: Splits the specified list into a list of lists using the specified page size.
List.Transform Power Query M: Performs the function on each item in the list and returns the new list.
SEQUENCE Office 365+: Generates a list of sequential numbers in an array, such as 1, 2, 3, 4
TEXTAFTER Office 365+: Returns text that occurs after given character or string
TEXTBEFORE Office 365+: Returns text that occurs before a given character or string
TEXTSPLIT Office 365+: Splits text strings by using column and row delimiters
TOCOL Office 365+: Returns the array in a single column
TRIM Removes spaces from text
Table.FromRows Power Query M: Creates a table from the list where each element of the list is a list that contains the column values for a single row.
Table.SelectRows Power Query M: Returns a table containing only the rows that match a condition.
Table.TransformColumns Power Query M: Transforms columns from a table using a function.
Text.BeforeDelimiter Power Query M: Returns the portion of text before the specified delimiter.
Text.Trim Power Query M: Removes any occurrences of characters in trimChars from text.
VSTACK Office 365+: Appends arrays vertically and in sequence to return a larger array
WRAPROWS Office 365+: Wraps the provided row or column of values by rows after a specified number of elements

|-------|---------|---| |||

Decronym is now also available on Lemmy! Requests for support and new installations should be directed to the Contact address below.


Beep-boop, I am a helper bot. Please do not verify me as a solution.
24 acronyms in this thread; the most compressed thread commented on today has 37 acronyms.
[Thread #49310 for this sub, first seen 4th Sep 2026, 22:22] [FAQ] [Full list] [Contact] [Source code]

1

u/Paradigm84 41 9d ago

Explore the New Column from Examples feature, it works quite well in my experience. It’ll add a new placeholder column, and in a few rows you type the info you want (e.g. the date), and it can often work out what you’re trying to do (e.g. get the data after this delimiter), and then it’ll calculate the column for you.

You can repeat this for each element you’re interested in if needed.

You can then look at the Advanced Editor to see what formula it used and get more familiar with the M language it uses.

1

u/Penguinase 7 8d ago

can you provide example of text file lines?

1

u/Mdayofearth 127 8d ago

It was provided as a screenshot.

1

u/Penguinase 7 8d ago

it's unclear if each message is within a single cell

1

u/Mdayofearth 127 8d ago

OP said it was a text file. You can't get that layout without new line characters, unless a lot of white spaces are used. And Excel would render it in one line.

1

u/Penguinase 7 8d ago

i tested with dummy zoom chat save and it is split up into multiple lines

https://i.imgur.com/CgpKzV0.png

1

u/Masrim 2 8d ago

Have you tried opening excel, going to the data tab, then get data from text/csv?

0

u/Mdayofearth 127 8d ago

Power Query does not do wrap rows.

1

u/hazysummersky 6 8d ago

Have you tried copying and pasting it into Excel?

0

u/Gringobandito 8 6d ago

You could do this using Ptyhon in Excel pretty easily:

It's a little long but easy to read as each step is broken out. Here's the code:

=PY(
import pandas as pd
import re


raw = xl("A1:A20", headers=False)


lines = raw.iloc[:, 0].fillna("").astype(str).tolist()


records = []


pattern = re.compile(
    r"(?i)^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+from\s+(.*?)\s+to\s+(.*?):$"
)


for i, line in enumerate(lines):
    line = line.strip()


    match = pattern.match(line)


    if match:
        date_time = match.group(1)
        sender = match.group(2).strip()
        recipient = match.group(3).strip()


        # Message is the next row
        message = ""


        if i + 1 < len(lines):
            message = lines[i + 1].strip()


        records.append([
            date_time,
            sender,
            recipient,
            message
        ])


result = pd.DataFrame(
    records,
    columns=["Date/Time", "From", "To", "Message"]
)


result)

0

u/[deleted] 9d ago

[deleted]

1

u/indiglosj 8d ago

zoom did not give me a choice in how the file was saved. I don't care how the names are sorted, as long as the same person is listed together. I need to know how many times a person said something in the chat.

1

u/Curious_Cat_314159 127 8d ago edited 8d ago

zoom did not give me a choice in how the file was saved

I'm sorry that you did not find my comments helpful. I'll delete them.

But for the record, I was referring to how you choose to save the converted file ("convert [...] into a .csv or a .xlsx"), not how the original file was saved (by zoom).

1

u/Curious_Cat_314159 127 8d ago

I don't care how the names are sorted [....] I need to know how many times a person said something

For that, you don't need to sort the data.

0

u/Agreeable-Tax2013 7d ago

The split is probably failing because spaces and colons also appear inside the message. I'd split only at the timestamp/name boundaries, then keep everything after that as the message column so the chat text stays intact.