Последние нули усекаются при получении внешних данных

При импорте данных из Интернета в Excel 2019 с выбором Data>Get Data>From Other Sources>From Web последние (конечные) нули чисел обрезаются, что приводит к появлению следующего столбца «Импорт»:

EU
Import | Desired
968,8  |  968800
891,01 |  891010
413,47 |  413470
410,3  |  410300
43,25  |   43250
17,8   |   17800
15,05  |   15050
3,61   |    3610
6,05   |    6050
4,9    |    4900

US
Import | Desired
968.8  |  968800
891.01 |  891010
413.47 |  413470
410.3  |  410300
43.25  |   43250
17.8   |   17800
15.05  |   15050
3.61   |    3610
6.05   |    6050
4.9    |    4900

Я хотел бы преобразовать данные, которые представляют собой текст (запятые, точки остаются разделителями тысяч), в числа, как в столбце Желаемое.

Я перестарался со следующей рабочей функцией VBA:

Option Explicit

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function UnTruncate(SourceVariant As Variant, _
  Optional TruncateString As String = "0", _
  Optional SplitSeparator As String = ",", _
  Optional NumberOfDigits As Long = 3) As Long

    Dim vnt As Variant        ' String Array (0-based, 1-dimensional)
    Dim strSource As String   ' Source String
    Dim strResult As String   ' Resulting String
    Dim strUB As String       ' Upper Bound String
    Dim i As Long             ' String Array Elements Counter

    ' Convert SourceVariant to a string (Source String (strSource)).
    strSource = CStr(SourceVariant)

    ' Check if Source String (strSource) is "" (UnTruncate = 0, by default).
    If strSource = "" Then Exit Function

    ' Split Source String (strSource) by SplitSeparator.
    vnt = Split(strSource, SplitSeparator)
    ' Assign the value of the last element in String Array (vnt)
    ' to Upper Bound String (strUB).
    strUB = vnt(UBound(vnt))

    ' Check if there is only one element in String Array (vnt). If so,
    ' write its value (strUB) to Resulting String (strResult) and go to
    ' ProcedureSuccess.
    If UBound(vnt) = 0 Then strResult = strUB: GoTo ProcedureSuccess

    ' Check if the length of Upper Bound String (strUB) is greater than
    ' NumberOfDigits. (UnTruncate = 0, by default)
    If Len(strUB) > NumberOfDigits Then Exit Function

    ' Add the needed number of TruncateStrings to Upper Bound String.
    strUB = strUB & String(NumberOfDigits - Len(strUB), TruncateString)

    ' Loop through the elements of String Array (vnt), from beginning
    ' to the element before the last, and concatenate them one after another
    ' to the Resulting String (strResult).
    For i = 0 To UBound(vnt) - 1: strResult = strResult & vnt(i): Next
    ' Add Upper Bound String (strUB) to the end of Resulting String (strResult).
    strResult = strResult & strUB

ProcedureSuccess:
    ' Convert Resulting String (strResult) to the resulting value of UnTruncate.
    UnTruncate = Val(strResult)

End Function
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

Но у меня такое чувство, что я упускаю некоторые важные моменты.

Я ищу другие решения: улучшение моей функции, формулу Excel, решение Power Query ... возможно, когда данные в столбце «Импорт» могут быть числами или текстом.


person VBasic2008    schedule 28.03.2020    source источник
comment
Может быть достаточно изменить десятичный разделитель с, на ....   -  person FaneDuru    schedule 28.03.2020
comment
Решение проблемы, похоже, зависит от типа данных. Почему бы нам просто не убрать запятую и точку и не умножить на 1000?   -  person Dy.Lee    schedule 28.03.2020
comment
@ Dy.Lee: Мои образцы данных делают это неочевидным, извините. Могли быть миллионы, миллиарды, потом было бы больше запятых. Но похоже хорошее решение для формулы Excel. Теперь просто укажите решение, если это был не текст, а число. Я нахожусь в Европе и скачал данные с американского веб-сайта. Так что для меня это могло быть десятичное число, но не более 1000000.   -  person VBasic2008    schedule 28.03.2020
comment
Возможно, с этим лучше всего справиться на этапе импорта, а не после.   -  person Ron Rosenfeld    schedule 28.03.2020
comment
@RonRosenfeld: Не могли бы вы предложить другой способ импорта, где я мог бы выбрать форматирование, потому что Excel «WebQuery» не допускает никаких изменений таким образом? Я посмотрел в свойствах диапазона данных и редактировании запроса.   -  person VBasic2008    schedule 28.03.2020
comment
вы можете очистить страницу с помощью xhr или автоматизации браузера. Есть ли URL?   -  person QHarr    schedule 28.03.2020
comment
Обычно есть опция Transform, где вы можете указать тип данных.   -  person Ron Rosenfeld    schedule 28.03.2020
comment
@QHarr: например, kworb.net/youtube, но я понятия не имею, что это за оба, если вы могли бы уточнить.   -  person VBasic2008    schedule 28.03.2020
comment
^ есть ли номер на этой странице, который будет обрезан для вас? И если да, то как он сейчас отображается для вас на странице? Описание: см. this и это   -  person QHarr    schedule 28.03.2020
comment
Используя ваш URL-адрес, если я использую Data -->Get & Transform --> From Web и выбираю Table0, он загружается со столбцами Views и Likes, правильно загруженными в виде чисел. Мне даже не нужно было никакого специального форматирования. Что ты делаешь по-другому?   -  person Ron Rosenfeld    schedule 28.03.2020
comment
@RonRosenfeld & QHarr: Я случайно использовал данные ›Получить данные› Legacy Wizards ›From Web (Legacy), то есть очень старую версию. После использования настоящей (новой) версии мне нужно было только удалить запятые (мой разделитель тысяч -.) В последних 2 столбцах и изменить тип на Number. Кстати, все это показало мне, что преобразование после этого невозможно, потому что как узнать, было ли это 2 или 2000, 20 или 20000 и т. Д. Ранее. Я изначально думал, что усечение - максимум 2 нуля. Настоящий урок для меня и пустая трата времени для вас. Извините. Спасибо за помощь.   -  person VBasic2008    schedule 28.03.2020
comment
@RonRosenfeld & QHarr: Если вы разместите подходящий ответ, я с радостью его приму. Если вы считаете, что вопрос бесполезен, я могу его удалить. Пожалуйста, порекомендуйте.   -  person VBasic2008    schedule 28.03.2020


Ответы (2)


Похоже, вы использовали Legacy Wizard, а не Power Query.

Если вы используете Power Query, после выбора таблицы выберите Transform.

Затем, если числовой столбец был импортирован как текст и показывает разделитель цифр запятой, не удаляйте запятые. Скорее:

  • Щелкните правой кнопкой мыши заголовок столбца
  • From the Right-Click dropdown menu:
    • Select Change Type --> Using Locale
    • Тип данных: целое число

введите описание изображения здесь

Это должно обо всем позаботиться.

РЕДАКТИРОВАТЬ:

Что касается сохранения гиперссылок из веб-таблицы с помощью Power Query, это не так просто, как с помощью Legacy Wizard, но вот метод, который, похоже, работает с вашим источником.

Для этого требуется три запроса и функция. И вам нужно будет отредактировать таблицу после загрузки, чтобы отформатировать числа и, возможно, гиперссылки.

  • Таблица запросов 0 Загрузить веб-таблицу без ссылок
  • Запросить getLinks Загрузить ссылки, связанные с видео
  • Query Merge1 Объедините два вышеуказанных запроса
  • Запрос fxExcelTrim Реплицируйте обрезку Excel, чтобы иметь возможность сопоставить названия видео в первых двух запросах, удалив лишние пробелы между словами в заголовке видео.

ExcelTrim

Введите приведенный ниже код в расширенный редактор пустого запроса

let ExcelTrim = (TextToTrim) =>
    let
        ReplacedText = Text.Replace(TextToTrim, "  ", " "),
        Result = if not(Text.Contains(ReplacedText, "  "))
            then ReplacedText
                else @ExcelTrim(ReplacedText)
    in
        Text.Trim(Result)
in
    ExcelTrim

Таблица 0

Обратите внимание, что я использовал функцию Changed Type with Locale, которая должна устранить проблему с выпадением нуля.

let
    Source = Web.Page(Web.Contents("https://kworb.net/youtube/")),
    Data = Source{0}[Data],
    #"Changed Type with Locale" = Table.TransformColumnTypes(Data, {{"Views", Int64.Type}, {"Likes", Int64.Type}}, "en-US"),
    #"Added Custom" = Table.AddColumn(#"Changed Type with Locale", "trimmedVideo", each ExcelTrim([Video]))
in
    #"Added Custom"

getLinks

let
    Source = Table.FromColumns({Lines.FromBinary(Web.Contents("https://kworb.net/youtube/"))}),
    #"Filtered Rows" = Table.SelectRows(Source, each Text.Contains([Column1], "href")),
    #"Filtered Rows1" = Table.SelectRows(#"Filtered Rows", each Text.Contains([Column1], "<div><a href=")),
    #"Added Custom" = Table.AddColumn(#"Filtered Rows1", "Link", each Text.BetweenDelimiters([Column1],"<a href=""","</a>")),
    #"Split Column by Delimiter" = Table.SplitColumn(#"Added Custom", "Link", Splitter.SplitTextByEachDelimiter({""">"}, QuoteStyle.None, false), {"Link.1", "Link.2"}),
    #"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Link.1", type text}, {"Link.2", type text}}),
    #"Removed Columns" = Table.RemoveColumns(#"Changed Type",{"Column1"}),
    #"Added Custom1" = Table.AddColumn(#"Removed Columns", "trimmedVideo", each ExcelTrim([Link.2])),
    #"Added Custom2" = Table.AddColumn(#"Added Custom1", "normLinks", each if not Text.StartsWith([Link.1],"http") then 
    "https://kworb.net/youtube/" & [Link.1] else 
    [Link.1])
in
    #"Added Custom2"

Слияние1

Возвращает ссылки в отдельном столбце от видео

let
    Source = Table.NestedJoin(#"Table 0", {"trimmedVideo"}, getLinks, {"trimmedVideo"}, "getLinks", JoinKind.LeftOuter),
    #"Added Custom" = Table.AddColumn(Source, "Links", each Table.Column([getLinks],"normLinks")),
    #"Extracted Values" = Table.TransformColumns(#"Added Custom", {"Links", each Text.Combine(List.Transform(_, Text.From)), type text}),
    #"Removed Columns" = Table.RemoveColumns(#"Extracted Values",{"trimmedVideo", "getLinks"})
in
    #"Removed Columns"

В качестве альтернативы вы можете использовать:

Объединить1 (2)

Возвращает HYPERLINK формулу в таблицу, которая содержит интерактивную ссылку с понятным именем.

let
    Source = Table.NestedJoin(#"Table 0", {"trimmedVideo"}, getLinks, {"trimmedVideo"}, "getLinks", JoinKind.LeftOuter),
    #"Added Custom" = Table.AddColumn(Source, "Links", each Table.Column([getLinks],"normLinks")),
    #"Replaced Value" = Table.ReplaceValue(#"Added Custom","""","""""",Replacer.ReplaceText,{"Video"}),
    #"Extracted Values" = Table.TransformColumns(#"Replaced Value", {"Links", each Text.Combine(List.Transform(_, Text.From)), type text}),
    #"Removed Columns" = Table.RemoveColumns(#"Extracted Values",{"trimmedVideo", "getLinks"}),
    #"Added Custom1" = Table.AddColumn(#"Removed Columns", "Linked Videos", each "=HYPERLINK(""" & [Links] & """," & """" &[Video] & """)"),
    #"Changed Type" = Table.TransformColumnTypes(#"Added Custom1",{{"Linked Videos", type text}}),
    #"Removed Columns1" = Table.RemoveColumns(#"Changed Type",{"Video", "Links"}),
    #"Reordered Columns" = Table.ReorderColumns(#"Removed Columns1",{"", "2", "Linked Videos", "Views", "Likes"})
in
    #"Reordered Columns"

Если вы используете Merge1 (2) для получения гиперссылок, после сохранения вам нужно будет выбрать столбец Linked Video и выполнить Find/Replace или = с =, чтобы преобразовать формулу из текстовой строки в формула. Если вы обновите запрос, вам нужно будет повторить этот процесс.

Вы также можете отформатировать столбцы Views и Likes, чтобы отобразить разделители тысяч.

Вот пример использования `Merge1 (2) с гиперссылками и разделителями тысяч.

введите описание изображения здесь

person Ron Rosenfeld    schedule 28.03.2020
comment
Я сделал это с помощью Locale, но я не заметил тип данных в этом окне и использовал контекстное меню, чтобы выбрать весь номер, и это не сработало. Теперь, когда вы смотрите на результат, он хорош, но бесполезен без гиперссылок. С помощью гиперссылок я создам 2 столбца с гиперссылками, один для kworb (статистика) и один для youtube (видео). Есть ли способ получить гиперссылки? Старый веб-запрос их получил. Я имею в виду, что смешно использовать старый веб-запрос, который медленно извлекает полный HTML-код, а затем новый только для двух столбцов, содержащих числа. Не так ли? - person VBasic2008; 29.03.2020
comment
@ VBasic2008 Вы вернулись и попробовали использовать окно Locale для установки как типа данных, так и страны? И это сработало? Я не понимал, что вам нужна гиперссылка. В Power Query это выполнимо, но сложно. Другой вариант - при использовании Legacy Wizard - изменить региональные настройки Windows на English - US перед импортом, а затем изменить их обратно. Для этого требуются вызовы Windows API (или изменения реестра), и на этом форуме есть примеры того, как это сделать. - person Ron Rosenfeld; 29.03.2020
comment
@ VBasic2008 Кстати, какой у вас родной разделитель тысяч и десятичный разделитель (из какой страны)? Если я что-то поменяю, при импорте я просто получу текстовую строку без пропущенных цифр. - person Ron Rosenfeld; 29.03.2020
comment
Мой разделитель тысяч - это точка (.). На данный момент я пришел к выводу, что это связано с Excel, поскольку, когда я копирую одно из этих критических чисел и вставляю их в Excel, он автоматически распознает их как десятичное число и обрезает «конечные» нули. С другой стороны, если я вставлю их в Блокнот или Word, результат останется неизменным. Таким образом, в Excel может быть параметр (возможно, проверка ошибок), который может быть причиной всего этого. Этот случай аналогичен тому, как если бы вы вставили некоторые данные с точкой в ​​качестве разделителя тысяч в Excel, и он распознал бы их как десятичное число. - person VBasic2008; 29.03.2020
comment
@ VBasic2008 Это не настройка Excel. Именно региональные настройки Windows определяют, как интерпретируются значения из устаревшего мастера импорта из Интернета. И в Power Query нет собственного метода, о котором я знаю, для сохранения гиперссылок во время импорта. AFAIK вам нужно получить гиперссылки отдельно, а затем объединить их с таблицей. Люди написали множество методов для этого, но я недостаточно продвинут в PQ, чтобы применить их к вашей конкретной проблеме. - person Ron Rosenfeld; 29.03.2020
comment
@ VBasic2008 Я добавил код, который позволяет использовать гиперссылки либо в отдельном столбце, либо в виде одного столбца с понятным именем. Может быть, у кого-то есть более простой метод, но это лучшее, что я мог сделать. - person Ron Rosenfeld; 29.03.2020
comment
Впечатляет, но довольно сложно. Я прошел через все это, и он работает, но он медленный, как LegacyQuery, с которым мне пришлось работать. Я изменил настройки «разделителя» с помощью VBA перед запросом и вернул их после запроса. Таким же образом я получил версию QHarr для работы. Вот ссылка на мою [Workbook] drive.google. com / open? id = 1_PjEQ_tGB0ESq1yKkAYAluwgmCUcqUdq. Сейчас меня определенно интересует Power Query, это какой-то SQL, и не могли бы вы предоставить ссылку, по которой я мог бы с ним познакомиться. Спасибо большое. Затем мне нужно будет улучшить версию QHarr еще одним вопросом. - person VBasic2008; 29.03.2020
comment
@ VBasic2008 Вы, конечно, можете объединить три запроса в один, но это все равно будет сложно. Возможно, когда-нибудь они добавят эту функциональность в собственный MCode. Что касается обучения, я предлагаю вам прочитать введение на MSDN. Затем поищите учебные пособия по спискам, записям и таблицам. А затем учебник по ключевому слову each. Документация MS не очень хороша, поэтому многое придется из практики, вопросов и чтения того, о чем другие пишут в блогах. - person Ron Rosenfeld; 30.03.2020

Это пример выдачи xhr на указанный вами URL и использования буфера обмена для копирования таблицы на лист. Цифры выглядят как на странице. Вам нужно иметь некоторое представление о html или, по крайней мере, знать, как щелкнуть правой кнопкой мыши по элементу (открыть вкладку элементов); Щелкните правой кнопкой мыши переключатель копирования на вкладке элементов инструментов разработчика - затем вы можете вставить этот селектор в html.querySelector("selector goes here").outerHTML; предполагая выбор стола.

Public Sub GetVideoInfo()
    Dim xhr As Object, clipboard As Object, html As MSHTML.HTMLDocument 'required VBE > Tools > References > Microsoft HTML Object Library

    Set clipboard = GetObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
    Set xhr = CreateObject("MSXML2.XMLHTTP")
    Set html = New MSHTML.HTMLDocument

    With xhr
        .Open "GET", "https://kworb.net/youtube/", False
        .send
        html.body.innerHTML = .responseText
    End With
    clipboard.SetText html.querySelector("#youtuberealtime").outerHTML
    clipboard.PutInClipboard
    ActiveSheet.Cells(1, 1).PasteSpecial
End Sub
person QHarr    schedule 28.03.2020
comment
Используя ваше решение, я снова получаю нежелательные результаты «старого» веб-запроса (столбец «Импорт»), вероятно, из-за проблем с языковым стандартом (ЕС-США). Я включил HTML ... в справочниках, нашел селектор запросов на веб-странице. Откуда взялось это число в GetObject? Поскольку это, вероятно, правильный путь, я бы дополнительно спросил вас, как извлечь «единственный» элемент, такой как «pagetitle», или отдельный столбец из таблицы со значениями, преобразованными в текст. Как это вообще возможно? Я видел усеченные ведущие нули, но «конечные» !? Не стесняйтесь игнорировать все это, поскольку вы уже многое сделали. - person VBasic2008; 29.03.2020
comment
GetObject использует GUID для буфера обмена форм ms. Это позднее связывание, но библиотеку для раннего связывания можно добавить через ссылки на проект (excel-macro.tutorialhorizon.com/) или добавив форму в свой проект. Что касается вывода, который вы получаете, не могли бы вы поделиться ссылкой на изображение вашего вывода? - person QHarr; 29.03.2020
comment
Для заголовка страницы должен работать html.querySelector (title) .innerText. Для одного столбца вы можете применить форматирование к листу после вставки или использовать querySelectorAll для сбора nodeList элементов в определенном столбце. Немного сложнее из-за ограниченного синтаксиса в реализациях парсера vba html, но вполне выполнимо. С радостью предоставлю примеры по запросу. - person QHarr; 29.03.2020